OpenAIのWhisper(v3)を使った音声認識・音声翻訳・音声識別
ESPnet2を使ってTextToSpeech(text2speech, テキスト読み上げ)とSpeechToText(speech2text, 音声書き起こし)をやりましたが、今回は、OpenAIのWhisperを使ってSpeechToTextを行なってみたいと思います(large-v3の動作も確認しました)。
ESPnet2に関しては、以下の記事を参考にしてください。
Whisperとは
WhisperはOpenAIの汎用音声認識モデルです。説明をみると、多言語音声認識(multilingual speech recognition)、音声翻訳(speech translation)、言語識別(language identification)ができるモデルだと書いてあります。
今回は、音声認識、音声翻訳、そして、音声識別のすべてを実験してみたいと思います。
Whisperのgithubリポジトリは、以下になります
Whisper(https://github.com/openai/whisper)
今回も、実験はGoogle Colabで行なっています。コードをGoogle Colabに順番にコピペして実行すれば動作確認を行うことができます。
今回も、Colabで動作確認できるコードをここに置いていますので、試したい方は利用してください。
パッケージのインストールとデータ準備
Whisperのインストール
Whisperのインストールです。
!pip install openai-whisper
上記のコードでインストールできるのですが、Colabの場合、上記でインストールすると、ランタイムの再起動が必要です。以下のコードでインストールすると再起動は必要ありません。ちなみに、公式ページに書かれている手順になります。
!pip install git+https://github.com/openai/whisper.git
データ準備
EPSnet2のText2Speechで作成した以下の音声を使って実験します。内容は、「吾輩は猫である」の冒頭部分になります。これを使う場合は、ダウンロードして、Colabのフォルダに転送してください。
Colabの左側のフォルダアイコンをクリックしてファイルを表示させ、そこにファイルをドラッグ&ドロップすればファイルを転送できます。
Whisperのインポート
Whisperをインポートします。
import whisper
モデルの読み込み
最初に、モデルを読み込みます。モデルには、「tiny」「base」「small」「medium」「large」があります。サイズ的には、tiny < base < small < medium < largeで、大きくなるほど性能が高いです。
Whisper v3のモデルも追加されています。モデルにlarge-v3を選ぶことでv3になります。v3では、精度がさらに向上しているようです。
今回は、mediumを選択しています。
model = whisper.load_model('medium')
baseとsmallの関係が、想像と逆でした
largeはColabのGPU(16GBだと)メモリ不足で動きませんでした。GPUを使わないようにすれば動きますがすごく遅いです。
large-v3であれば、ColabでもGPUで動作するようです(2023.11.25追記)
音声認識(文字起こし、Speech2Text)
EPSnet2も手軽でしたが、それと比べても簡単です。transcribe
に音声ファイルを設定するだけでした。前回のようにサンプリングレートなどの設定もなく簡単です。
result = model.transcribe('test.wav')
print(result['text'])
結果は以下になります。かなり正確に文字起こしされていることがわかります。
"我が輩は猫である。名前はまだない。どこで生まれたかとんと検討がつかぬ。なんでも薄暗いじめじめしたところでにゃあにゃあ泣いていたことだけは記憶している。"
EPSnet2では「我が輩は猫である名前はまだないどこで生まれたかとんと検討が付かぬ何でも薄暗いじめじめしたところでにおいには泣いていたことだけは記憶している」でしたので、mediumだと少し性能が高いみたいです。
音声翻訳
次は音声翻訳です。こちらも、languageにターゲットの言語を設定するだけなので簡単です。
result = model.transcribe('test.wav', language="en")
print(result['text'])
結果は、以下になります。なんとなくあってそうです。
" I am a cat. I don't have a name yet. I don't know where I was born. I only remember crying in a place where everything was so dark and damp."
言語識別
言語識別です。こちらは最初にメルスペクトログラムに直す必要があるようです。
Mel Spectrogramに変換
メル・スペクトログラムに変換した結果は画像としてみることができますので、まず画像にして確認にしてみます。
import matplotlib.pyplot as plt
audio = whisper.load_audio("test.wav")
mel = whisper.log_mel_spectrogram(audio)
plt.imshow(mel)
音声処理ではお馴染みのメルスペクトラムです(縦横の単位は画素です)
メル・スペクトログラムへの変換はlarge-v3モデルで実行すると、エラーになります(チャネル数が足りないというエラーがでます)
言語識別
言語識別はメル・スペクトログラムに変換→パディング→推定の流れで行うようです。
audio = whisper.pad_or_trim(audio)
mel = whisper.log_mel_spectrogram(audio).to(model.device)
_, probs = model.detect_language(mel.to(model.device))
print(f"Detected language: {max(probs, key=probs.get)}")
結果は以下の通りで、日本語と認識できているようです
Detected language: ja
サンプリングレートを変えて入れてみる
EPSnet2では、サンプリングレートを合わせないとうまく動かなかったので、サンプリングレート関連がどうなっているか気になりました。ということで、サンプリングレートを変更して入れてみます。
まずは、変換なし
import librosa
speech, sr = librosa.core.load("test.wav")
result = model.transcribe(speech)
print(result['text'])
"わがはいは猫である 名前はまだないどこで生まれたかとんと 検討がつかぬなんでも薄暗いじめじめしたところでにゃあにゃあ泣いていたことだけは 記憶している"
我が輩がひらがなになったので、音声ファイル名を引数とした場合と挙動が変化したみたいです。ただ、結果は問題なさそうです。次は、16000Hzに変換
speech, sr = librosa.core.load("test.wav", sr =16000)
result = model.transcribe(speech)
print(result['text'])
”我が輩は猫である。名前はまだない。どこで生まれたかとんと検討がつかぬ。なんでも薄暗いじめじめしたところでにゃあにゃあ泣いていたことだけは記憶している。”
音声ファイルを直接入力したときと同じ結果になりました。音声ファイルの場合は、適切なサンプリングレートに変換されているようです。
Whisperはサンプリングレートが異なってもある程度は認識できるみたいです(合わせたほうが良いとは思いますが)。
まとめ
以上、Whisperを使って、文字起こし、翻訳、言語推定をやってみました。ライブラリの性能が上がってきて本当に簡単にできるようになりました。本当に使い方(アイデア次第)次第です。