今回はゆるめで、あるイベントのLTに参加してきた感想やら、資料やら動画やらソースコードを共有するだけの記事となっております。
ことの成り行き
Tokyo.Rでお世話になっているy__mattuさんから、「Music×Analytics Meetup Vol.4」のイベントのことを教えていただき、せっかくなのでLTをさせてもらえることになりました。
音楽の分析に関して入門レベルなので果たして参加者が盛り上がってくれる何かを提供できるか不安でした。
納期的にも、今の実力的にも過去に書いたブログ([Python]スペクトグラムで楽器の試奏データを比較(プロ奏者とも))の延長線上のことでいいなと思ったんですが、
先行研究は欲しいし、分析対象の音楽もスケール(音階)ではなく何かの曲が良いと思いました。あと、意外な情報も載せたい、分析結果を活かして便益を得たいとも思いました。
なので、LTまでに先行研究を見つけ、意外な情報としてjupyter notebookで録音する機能を見つけ、分析対象の曲にギャツビーのCMのものを採用しました。
そして、この研究から自分の楽器の演奏の腕前を向上させることができました。
これならLTとして発表しても入門レベルでも楽しいのではないかなと思いました。
LT内容
Google Presentationと事前に録音したYoutubeをこちらに載せておきます。
発表音声の文字起こし
LTを7分以内に抑えるリハーサルをした際の音声があったので、それをGoogle Speech To Text APIを使って文字起こしをしておきます。
「それではその音に近づくための研究と練習ということで江口さん自己紹介ですが名前は救えバックグランドは経済学や統計学仕事では同席部のマネージャー兼データ分析さんはこんな感じで趣味はトランペットブログ作成をやってるので良かったみてください結局どうしたんですけどその他データ分析関連のかって言いよったでどうやって勝手の音消したいなって思いますがここまでのホスピスがまずあって写真撮って進度が速い遅いである時と言うとって治ってるということですが音の長さが変わりますなのでお体変わります秘密のピストンだけなので発送の仕方ありませんのでコントロールして40種類ぐらいのレベルからは死んだことに帰って前記処理学会のそれの大会でスペクトルグラムを使ってプロのアクセスをしたのとの比較ではその方向の出来不出来を判定すると犬が行われていました鬼時間に周波数色の濃淡で信号ってなっちゃったから明日グラフとなりますがこの場合は時間が12秒まであって周波数が8000まで行ってあのね精神旺盛な強さが違ってます本当の鳴き声何もとしてるの俺も行ってここだったから体操マット耐熱耐酸プルマンちょっと寄りますよねプレイヤーの力も貸したして自分との違いを明らかにして違いがある場合とならそこによるそれが産めるのかお話していきたいと思ってます結果こんな感じえーとまずはサイトメトロ ffmpeg をインストールしてああいパイソン mrtg をインストールしたギターの音は愛想の良いしらすを呼び出してこういう形で書くことでノートブックので他のところでエロ金ボタンが現れますこれ音声は録音開始でもう一度録音するようになっていますその後に録音したファイルを保存 SMS でまあ16000hz 2のファイルに変換してまた再読み込みという形があってもはい録音環境としてはわからないぞマイクでして何楽器はちょっと古いので今回あったのがという音楽などの分析見ております玄関のために必要なセッティングってのがあるんでは基本的なセッティングで言っても実際に自分のそれかしたら私に出てきますね自分のやってみようと思いますまず聞いてみましょう第4フォルマント信号の強さがえっと Pro は赤いんですけど強いんですけど出してもらうわいえ私なってます遅く音源第4フォルマントの方がやっぱり行けないなっていうのが分かれば鼻が詰まってるから行けないっていましたねと自分ではまあ剛てる所間違いが分かりましたどうしたら強い信号になってるのかその女お腹に力を入れる行きの数量変えるとかありますもうなんかの力を入れて強いわ強い力を込めてもっと明るくならなかったにやと言われるとも出てこなくなったよ沢山入ったとこですねこれで第4子が赤くなるのはこれまで行きの量が足りてなかった自分じゃなかったじゃないかっていうので行ってみましょう早くなりましたねでスタグラムに従ってくると自分の音が帰宅したところ息を吸う量を多くすることで気分良くなることがわかりました待機するのって管楽器重要な今なってどれぐらい剃ったらいいのか分かんなかったり根性論だったりするんでこれは便利だねまあは管楽器にも分からなくなって鳴るんですけど G 計り方とかあると結婚もしないからっても行きたいのでくれてありがとうございました」
ソースコード(LT)
こちらではLTのために使ったスペクトログラムを表示するためのコードを共有します。
1 2 3 4 5 |
# 録音用のコード from ipywebrtc import AudioRecorder, CameraStream camera = CameraStream(constraints={'audio': True,'video':False}) recorder = AudioRecorder(stream=camera) recorder |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 変換と読み込み用のコード from IPython.display import Audio from scipy.io import wavfile import numpy as np with open('recording.webm', 'wb') as f: f.write(recorder.audio.value) !ffmpeg -i recording.webm -ac 1 -ar 16000\ -f wav file.wav -y -hide_banner -loglevel panic sr, sig = wavfile.read("file.wav") Audio(sig, rate=sr) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# スペクトログラム表示用 import numpy as np from scipy.io import wavfile from IPython.display import Audio import librosa import librosa.display import matplotlib.pyplot as plt sr, sig = wavfile.read("file.wav") # 16bitの音声ファイルのデータを-1から1に正規化 data = sig / 32768 # フレーム長 fft_size = 1024 # フレームシフト長 hop_length = int(fft_size / 4) # 短時間フーリエ変換実行 amplitude = np.abs(librosa.core.stft(data, n_fft=fft_size, hop_length=hop_length)) # 振幅をデシベル単位に変換 log_power = librosa.core.amplitude_to_db(amplitude) # グラフ表示 librosa.display.specshow(log_power, sr=sr, hop_length=hop_length, x_axis='time', y_axis='hz') plt.colorbar(format='%+2.0f dB') plt.title('player 1') plt.show() |
ソースコード(文字起こし)
Google Speech To Text APIで文字起こしをする際のコードをここに載せておきます。
1 2 3 4 |
# ffmpegでの処理 ffmpeg -y -i audio_only.m4a -ac 1 audio_only.wav ffmpeg -y -i audio_only.wav -af "highpass=f=200, lowpass=f=3000" audio_only_filtered.wav ffmpeg -y -i audio_only_filtered.wav -ar 44100 audio_only_filtered_441.wav |
GCSのバケットを作っておきます。今回はperry_voiceという名前のバケットを作っておきました。先ほど作ったaudio_only_filtered_441.wavを、このバケットにあげておきます。
APIの認証用のjsonファイルをcloud shellにアップロードしておきます。jsonファイルはGCPのコンソールの認証情報からサービスアカウントキーを作成し、「鍵を追加」の項目からjsonファイルを選択して手に入れることができます。(当然、Google Speech To Text APIのAPIを有効にしておく必要があります。)
1ヶ月につき60分までは無料なので、今回の処理も無料でできます。(GCSは数円かかると思いますが。)
1 2 3 4 5 |
# cloud shellの設定 pip install google.cloud pip install google-cloud-speech pip install --upgrade google-cloud-storage export GOOGLE_APPLICATION_CREDENTIALS="認証用のjsonファイル名" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# cloud shell上で実行するPythonコード(speech2text_run.pyとして保存) # !/usr/bin/env python # coding: utf-8 import argparse import io import sys import codecs import datetime import locale import re from google.cloud import storage def upload_blob(bucket_name, source_file_name, destination_blob_name): """Uploads a file to the bucket.""" storage_client = storage.Client() bucket = storage_client.get_bucket(bucket_name) blob = bucket.blob(destination_blob_name) blob.upload_from_filename(source_file_name) def transcribe_gcs(gcs_uri): from google.cloud import speech_v1 as speech from google.cloud.speech_v1 import enums from google.cloud.speech_v1 import types client = speech.SpeechClient() audio = types.RecognitionAudio(uri=gcs_uri) # d_config = types.SpeakerDiarizationConfig( # enable_speaker_diarization=False, # min_speaker_count=2, # max_speaker_count=3 # ) config = types.RecognitionConfig( sample_rate_hertz=44100, encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16, language_code='ja-JP', audio_channel_count=1, # enable_word_time_offsets=True, profanity_filter=True, # diarization_config=d_config, # min_speaker_count=2, # max_speaker_count=3 speech_contexts=[types.SpeechContext( phrases=["トランペット"])] ) operation = client.long_running_recognize(config, audio) print('Waiting for operation to complete...') operationResult = operation.result() uri = re.sub('gs://perry_voice/', '',gcs_uri) fout2 = codecs.open('{}_output.txt'.format(uri), 'a', 'shift_jis') for result in operationResult.results: alternative = result.alternatives[0].transcript fout2.write(alternative) fout2.close() upload_blob('perry_voice','{}_output.txt'.format(uri), '{}_output.txt'.format(uri)) if __name__ == '__main__': parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( 'path', help='GCS path for audio file to be recognized') args = parser.parse_args() transcribe_gcs(args.path) |
1 2 |
# cloud shellでPythonコードをキックする用 python speech2text_run.py gs://perry_voice/audio_only_filtered_441.wav |
文字起こし結果はGCSのperry_voiceの中にあります。
他の発表から学んだこと
深層学習を用いたJazz音楽の研究や、音楽の理論、DJプレイの自動化の研究、声の変換技術など同じ音という題材ながらも幅広く話を聞くことができました。私だけ入門な内容で申し訳ない気持ちが生じましたが、これからこの分野を深めるのもプレイヤーとして面白いなと思ったので、長く学ばせてもらおうと思います。
懇親会で学んだこと
・NVIDIAのノイズリダクション技術は文字起こしの際にやってみる価値あり
・賃貸の場合、防音の部屋は家賃相場の2~3万円アップ
・口周辺の筋肉の研究をされている方がいる(論文でその分野があるのは知っていたが、実験をやっていた方に会えた)
・みな、条件を揃えるためにマイクや集音の仕方にこだわりがあった。
・いい音の定義にやはり答えはない。