Пример #1
0
def m4a_to_mp3(input_file_path):
    # パスから、拡張子と名前を分ける
    root, ext = os.path.splitext(input_file_path)
    logger.info('start m4a to mp3 convert {}'.format(input_file_path))
    # s3にアップロード
    # upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),'log_2nd/{}'.format(logging_file))
    if ext not in ['.m4a', '.mp4']:
        logger.debug('input file: {}'.format(str(input_file_path)))
        return
    if os.path.exists('tmp/') is not True:
        logger.info('make directory to mp3_files')
        # upload_s3.sign_s3(
        # 'tmp/analize_log//{}'.format(logging_file), 'log_2nd/{}'.format(logging_file))
        os.mkdir('tmp/')
    # 変換するmp3ファイルの名前
    input_file_path_mp3 = '%s.mp3' % root
    # set commands for m4a to mp3 using ffmpeg
    cmd = 'ffmpeg -i %s -ab 64k -ar 16000 %s' % (input_file_path,
                                                 input_file_path_mp3)
    # upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),'log_2nd/{}'.format(logging_file))
    logger.info('converted mp3 file: {}'.format(input_file_path_mp3))
    logger.info(cmd)
    # do m4a to mp3(どちらもバイナリではなくパスを指定すること)
    status, output = subprocess.getstatusoutput(cmd)
    if status != 0:
        logger.error('failed convert {0}, {1}'.format(status, output))
        return input_file_path_mp3
    # S3にアップロード
    # upload_s3.sign_s3(input_file_path_mp3,
    #   'mp3_2nd/{}.mp3'.format(root.strip('/tmp/')))
    logger.info('Done converted\nstatus: {0}\noutput: {1}'.format(
        status, output))
    # mp3ファイルパスを返す
    return input_file_path_mp3
Пример #2
0
def detect_chords(input_file):
    """ 音声データからコードを取得する """
    endpoint = 'analyze/chords'  # コード解析APIのエンドポイント
    # 必要なパラメータをセットする
    url, datas, files = set_param_to_api(endpoint, input_file)
    logger.info('set param: url: {0}, datas: {1}, file: {2}'.format(
        url, datas, files))
    # Sonic APIに音声データを投げる
    res = r.post(url=url, data=datas, files=files, verify=False)
    logger.info('analyzed result: {}'.format(res))

    return res.text
Пример #3
0
def set_response_chord_analize(analize_chord_s):
    """
    :param analize_chord:
    :return: chord_analize_response
    """
    logger.info('Do make for response: {}'.format(analize_chord_s))
    # str型を辞書型に変換
    analize_chord_j = json.loads(analize_chord_s)
    logger.info('str count of result'.format(len(str(analize_chord_s))))
    # 総検出数
    num_chords = analize_chord_j['chords_result']['num_chords']
    # コードのみを格納する辞書を用意する
    chords_list = []
    # 取りたい項目を決める(今回は'chords')
    for key, value in enumerate(analize_chord_j['chords_result']['chords']):
        if value['chord'] == 'N':
            continue
        # コードのみ抽出
        chord = value['chord']
        # リストに格納
        chords_list.append(chord)
    logger.info(
        'Result Analized number of chord: {0}, Chord Progression{1}'.format(
            num_chords, chords_list))
    logger.info('number of string count in Response: {}'.format(
        len(str(chords_list))))
    if len(str(chords_list)) > 2000:
        chords_list = str(chords_list)[0:1999]

    return chords_list
Пример #4
0
 def youtube2midi(self, youtube_url, user_id):
     # youtubeのurlをmp4ファイルにダウンロード
     mp4 = youtube2mp3(youtube_url, user_id)
     # mp4ファイルをmp3に変換
     mp3 = m4a_to_mp3(mp4)
     logger.info("mp3 file: {}".format(mp3))
     # mp3のコード解析
     chord_analyze_str = detect_chords(str(mp3))
     # 辞書型に変換
     chord_analyze_dict = ast.literal_eval(chord_analyze_str)
     logger.info("change type {0} to {1}".format(type(chord_analyze_str),
                                                 type(chord_analyze_dict)))
     # midiファイルに変換
     chords2midi(chord_analyze_dict, user_id)
Пример #5
0
def youtube2mp3(youtube_url, line_userid):
    logger.info('youtube url: {}'.format(youtube_url))
    print('youtube url: {}'.format(youtube_url))
    # S3にアップロード
    # upload_s3.sign_s3(youtube_url, 'youtube_url/{}'.format(youtube_url))
    # youtube動画を抜き出す
    yt = YouTube(youtube_url)
    # 動画の情報を出力
    for lis in yt.streams.all():
        logger.info(lis)
    # get_bu_itagtodownloadメソッドででダウンロードができる
    yt2mp3 = yt.streams.get_by_itag(140).download('/tmp/')
    logger.info('youtube video converted to mp4 {}'.format(yt2mp3))
    # LINEのuseridにrenameする
    input_file_path = '/tmp/{}.mp4'.format(line_userid)
    os.rename(yt2mp3, input_file_path)
    # mp3ファイルを5分にカットする
    mp4 = AudioSegment.from_file(input_file_path, format='mp4')
    # 0~500sec(300000ms)にカット
    mp4_1min = mp4[0:60000]
    # logger.info('rename: {}'.format(os.rename(yt2mp3, 'tmp/{}.mp4'.format(line_userid))))
    logger.info('Receive mp4 file name: {}'.format(input_file_path))
    # with open(yt2mp3, 'wb') as fb:
    #     fb.write(yt2mp3)

    return input_file_path
Пример #6
0
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    logger.info('Request body: ' + str(body))
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'log_2nd/{}'.format(logging_file))
    # hadle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'
Пример #7
0
async def basic_async(num, sleepingtime):
    """
    処理の中核
    :return:
    """
    logger.info('basic async')
    # awaitでsleeptingの処理が終わるのを待ってる
    for t in task:
        r = await sleeping(order, t)
        logger.info('await sleeping')
        logger.info("{0}'s {1} is finished".format(num, r))
        index = +1
        logger.info('index {}'.format(index))
        time.sleep(5)
        logger.info('basic_async time {} [sec]\n'.format(sleepingtime))
    return True
Пример #8
0
def m4a_to_mp3(input_file_path):
    # パスから、拡張子と名前を分ける
    root, ext = os.path.splitext(input_file_path)
    logger.info('start m4a to mp3 convert {}'.format(input_file_path))
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'mico/log/{}'.format(logging_file))
    if ext not in ['.m4a', '.mp4']:
        logger.debug('input file: {}'.format(str(input_file_path)))
        return
    if os.path.exists('/tmp/') is not True:
        logger.info('make directory to mp3_files')
        upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                          'mico/log/{}'.format(logging_file))
        os.mkdir('/tmp/')
    # 変換するmp3ファイルの名前
    input_file_path_mp3 = '%s.mp3' % root
    # set commands for m4a to mp3 using ffmpeg
    cmd = 'ffmpeg -i %s -ab 64k -ar 16000 %s' % (input_file_path,
                                                 input_file_path_mp3)
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'mico/log/{}'.format(logging_file))
    logger.info('converted mp3 file: {}'.format(input_file_path_mp3))
    logger.info(cmd)
    # do m4a to mp3(どちらもバイナリではなくパスを指定すること)
    status, output = subprocess.getstatusoutput(cmd)
    if status != 0:
        logger.error('failed convert {0}, {1}'.format(status, output))
        return input_file_path_mp3
    # S3にアップロード
    upload_s3.sign_s3(input_file_path_mp3,
                      'mico/mp3/{}.mp3'.format(root.strip('/tmp/')))
    logger.info('Done converted\nstatus: {0}\noutput: {1}'.format(
        status, output))
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'mico/log/{}'.format(logging_file))
    # 保存
    # with open(input_file_path_mp3, 'rw') as fb:
    #     fb.write(input_file_path_mp3)
    # # mp3ファイルを5分にカットする
    # mp3 = AudioSegment.from_file(input_file_path_mp3, format='mp3')
    # # 0~500sec(300000ms)にカット
    # mp3_5min = mp3[0:300000]
    # mp3ファイルパスを返す
    return input_file_path_mp3
async def basic_async_2(msg, sleepingtime):
    """
    処理の中核
    :return:
    """
    index = 0
    while True:
        logger.info('\nbasic async')
        r = await sleeping(msg, sleepingtime)
        logger.info('await sleeping')
        # これをやってる間に
        logger.info("SUB task count {}".format(index))
        time.sleep(sleepingtime)
        logger.info('2basic_async time {} [sec]\n'.format(sleepingtime))
        index = +1
Пример #10
0
async def sleeping(order, time_limit, hook=None):
    """
    「重いけど処理順は問わない」処理。
    重たい処理(m4aの読み込み。mp3に変換)はここで行う。
    """
    logger.info('sleeping 10sec')
    # awaitが行われるということは何か重たい処理が始まるということ
    await asyncio.sleep(time_limit)
    logger.info('await asyncio.sleep')
    if hook:
        hook(order)
    a = time.sleep(2)
    logger.info('sleeping time {} [sec]\n'.format(2))
    return order
Пример #11
0
def youtube2mp3(youtube_url, line_userid):
    logger.info('youtube url: {}'.format(youtube_url))
    # S3にアップロード
    # upload_s3.sign_s3(youtube_url, 'youtube_url/{}'.format(youtube_url))
    # youtube動画を抜き出す
    yt = YouTube(youtube_url)
    logger.info(yt)
    # 動画の情報を出力
    for lis in yt.streams.all():
        logger.debug(lis)
    # get_bu_itagtodownloadメソッドででダウンロードができる
    yt2mp3 = yt.streams.get_by_itag(140).download('tmp/')
    logger.info('youtube video converted to mp4 {}'.format(yt2mp3))
    # LINEのuseridにrenameする
    input_file_path = 'tmp/{}.mp4'.format(line_userid)
    os.rename(yt2mp3, input_file_path)
    # logger.info('rename: {}'.format(os.rename(yt2mp3, 'tmp/{}.mp4'.format(line_userid))))
    logger.info('Receive mp4 file name: {}'.format(input_file_path))
    # with open(yt2mp3, 'wb') as fb:
    #     fb.write(yt2mp3)

    return input_file_path
async def sleeping(t, sleepingtime, hook=None):
    """
    「重いけど処理順は問わない」処理。
    重たい処理(m4aの読み込み。mp3に変換)はここで行う。
    """
    # logger.info('sleeping {} sec')
    logger.info('sleeping: {}'.format(t))
    # awaitが行われるということは何か重たい処理が始まるということ
    await asyncio.sleep(t)
    logger.info('await asyncio.sleep TASK: {}'.format(t))
    if hook:
        hook(order)
    time.sleep(sleepingtime)
    logger.info('sleeping time {} [sec]\n'.format(sleepingtime))
    return order
Пример #13
0
def handle_message(event):
    if event.message.type is not 'audio':
        # 入ってきたものがaudio以外だったら、デフォルトメッセージを返す
        start_youtube_time = time.time()
        for i in range(1, MAX_RETRY):
            try:
                line_bot_api.reply_message(
                    event.reply_token,  # トークンとテキストで紐づけてる
                    TextSendMessage(text='あなたと一緒にコード解析するよー!\n'
                                    'LINEで録音して送ってみてね。\n'
                                    '容量の小さいmp3ファイルも解析できるよ'))
                break
            except LineBotApiError as e:
                logger.error('LineBotApiError: {}'.format(e))
                logger.error('retry: {0}/{1}'.format(i, MAX_RETRY))
                line_bot_api.reply_message(
                    event.reply_token,  # トークンとテキストで紐づけてる
                    TextSendMessage(text='あなたと一緒にコード解析するよー!\n'
                                    'LINEで録音して送ってみてね\n'
                                    '容量の小さいmp3ファイルも解析できるよ\n'))

        return 'ok'
    logger.info('Message ID: {}'.format(str(event.message.id)))
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'log_2nd/{}'.format(logging_file))
    # オーディオデータ(バイナリ形式。'audio/x-m4a')を取得する
    message_content = line_bot_api.get_message_content(event.message.id)
    # tmpディレクトリに保存
    input_file_path = '/tmp/{}.m4a'.format(event.message.id)
    logger.info('Receive m4a file name: {}'.format(str(input_file_path)))
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'log_2nd/{}'.format(logging_file))
    if os.path.exists('/tmp/') is not True:
        logger.info('make temporary directory')
        os.mkdir('/tmp/')

    # line_bot_api.push_message(
    #     event.source.user_id,  # トークンとテキストで紐づけてる
    #     TextSendMessage(text='解析してみるよー!\n'
    #                          '終わったら話しかけるねー。\n'
    #                          '1分経ってもお返事が来なかったら、もう少し短いファイルを送ってみてくれるかな?')
    # )
    start_chunk = time.time()
    with open(input_file_path, 'wb') as fd:
        for i in range(MAX_RETRY):  # m4aバイナリの書き込みに失敗したら、5回までリトライ処理入れる
            try:
                for chunk in message_content.iter_content():
                    fd.write(chunk)
                break
            except:
                logger.error('LineBotApiError: {}'.format(
                    traceback.format_exc()))
                logger.error('retry: {0}/{1}'.format(i, MAX_RETRY))
                sleep(i * 5)
        end_chunk = time.time() - start_chunk
        logger.info('chunk time: {}'.format(end_chunk))
        start_conv_mp3 = time.time()
        # S3にアップロード
        upload_s3.sign_s3(input_file_path,
                          'm4a_2nd/{}.m4a'.format(event.message.id))

    # m4aバイナリファイルをローカルに保存し、mp3バイナリファイルに変換する
    chunk_mp3 = song_upload.m4a_to_mp3(input_file_path)
    end_conv_mp3 = time.time() - start_conv_mp3
    logger.info('converted time: {} [sec]'.format(end_conv_mp3))
    start_analize = time.time()
    chord_analize_response = mp3_to_response(chunk_mp3)
    end_analize = time.time() - start_analize
    logger.info('Analize time: {} [sec]'.format(end_analize))
    # push API使えないバージョン
    # line_bot_api.reply_message(
    #     event.reply_token,  # トークンとテキストで紐づけてる
    #     TextSendMessage(
    #         text=
    #         str(chord_analize_response)
    #     )
    # )
    line_bot_api.reply_message(
        event.reply_token,  # トークンとテキストで紐づけてる
        TextSendMessage(text=str(chord_analize_response)))
    logger.info(
        'Success! Sent response for user: {}'.format(chord_analize_response))
    # S3にアップロード
    upload_s3.sign_s3('/tmp/analize_log//{}'.format(logging_file),
                      'log_2nd/{}'.format(logging_file))
    return 'ok'
Пример #14
0
def check_timeout(push, loop=None):
    logger.info('check timeout')
    if loop is None:
        loop = asyncio.get_event_loop()
        loop.stop()  # イベントループをとめて制御をもどす処理を追加
Пример #15
0
    """
    処理の中核
    :return:
    """
    logger.info('basic async')
    # awaitでsleeptingの処理が終わるのを待ってる
    for t in task:
        r = await sleeping(order, t)
        logger.info('await sleeping')
        logger.info("{0}'s {1} is finished".format(num, r))
        index = +1
        logger.info('index {}'.format(index))
        time.sleep(5)
        logger.info('basic_async time {} [sec]\n'.format(sleepingtime))
    return True


if __name__ == "__main__":
    # 処理の実行を担うのがこのイベントグループ。
    # これが「ノンブロッキングなスレッド」
    loop = asyncio.get_event_loop()
    logger.info('make loop')
    # 2のタスクを生成する。
    # 一つの処理がawaitに入ったら次の処理をしてを繰り返す
    # while True:
    asyncio.ensure_future(basic_async(1, 2))
    logger.info('done basic_async 1')
    asyncio.ensure_future(basic_async(2, 5))
    logger.info('done basic_async 2')
    # 2つの処理が終わるまで繰り返す
    loop.run_forever()
Пример #16
0
def chords2midi(chords_dict, file_name):
    # pretty midiオブジェクトを作る
    piano_chord = pretty_midi.PrettyMIDI()

    # 楽器名を入れると、対応するgeneral midi program numberを返す
    piano_program = pretty_midi.instrument_name_to_program('Acoustic Grand Piano')

    # Instrument instanceをcelloとして作成
    piano = pretty_midi.Instrument(program=piano_program)

    # 解析したコードを単音のリストにバラす
    for i, chord in enumerate(chords_dict["chords_result"]["chords"]):
        logger.info(i, chord)
        # Nの時はスキップ(ノートに書き込まない)
        if chord['chord'] == "N":
            continue
        chords_list = key2chord(chord)
        logger.info("chords list: {}".format(chords_list))
        logger.info("start time: {}".format(chord["time"]))
        logger.info("end time: {}".format(chords_dict["chords_result"]["chords"][i+1]["time"]-0.1))
        # print("time: {}".format(float(chords_dict["chords_result"]["chords"][i+1]["time"])-float(chord["time"])))
        for note_name in chords_list:
            # コードの名前を数字に変換
            note_number = pretty_midi.note_name_to_number(note_name)
            logger.info("chord name {0}, chord num {1}".format(note_name, note_number))
            # velocityを定義する
            try:
                note = pretty_midi.Note(
                    velocity=100,
                    pitch=note_number,
                    start=chord["time"],
                    end=chords_dict["chords_result"]
                            ["chords"][i+1]["time"]-0.1
                )
                # print(note)
                # 上記で作成したnoteをchelloインスタンスに加える
                piano.notes.append(note)
            except IndexError:  # 最後の章は0.5秒とする
                logger.info("note last code")
                note = pretty_midi.Note(
                    velocity=100,
                    pitch=note_number,
                    start=chord["time"],
                    end=chord["time"]+0.5
                )
                # 上記で作成したnoteをchelloインスタンスに加える
                piano.notes.append(note)
    # PrettyMIDIオブジェクトに加える
    piano_chord.instruments.append(piano)
    print(piano)
    print(piano_chord)
    midi_file = "midi/" + str(file_name) + ".mid"
    # MIDIファイルとして書き出す
    piano_chord.write(midi_file)

    # Load MIDI file into PrettyMIDI object
    midi_data = pretty_midi.PrettyMIDI(midi_file)
    # Print an empirical estimate of its global tempo
    print(midi_data.estimate_tempo())
Пример #17
0
def mp3_to_response(data_mp3):
    logger.info('Do analizing mp3 data: {}'.format(data_mp3))
    # mp3を引数にして、コード解析APIに投げる
    analize_chord = chord_analize.detect_chords(input_file=data_mp3)
    # str型なので、JSON形式に変換する
    analize_chord_j = json.loads(analize_chord)
    logger.info('Response Header: {}'.format(analize_chord))
    if analize_chord_j['status']['code'] == (200 or 201):
        # 得られたレスポンスを成形する
        chord_analize_response = set_response.set_response_chord_analize(
            analize_chord)
        logger.info('Made Response:{} '.format(str(chord_analize_response)))
        return chord_analize_response
    elif analize_chord_j['errors']:
        if analize_chord_j['errors'][0]['error_code'] == '23':
            chord_analize_response = 'オーディオファイルが短すぎるみたい。\n15秒以上にしてもう一回送ってみてね!'
            logger.info('Made Response: '.format(chord_analize_response))
            return chord_analize_response
        elif analize_chord_j['errors'][0]['error_code'] == '22':
            chord_analize_response = '私の知らないファイル形式かも。\n' \
                                     'mp3形式かaac形式しか今はわからないんだ、、。\nあなたは物知りで凄いなぁ'
            logger.info('Made Response: '.format(chord_analize_response))
            return chord_analize_response
        else:
            chord_analize_response = 'ちょっと調子が悪いみたい。\nもう一回試してみてもらえるかな?'
            logger.info('Made Response: '.format(chord_analize_response))
            return chord_analize_response