OpenAIのWhisper v3による音声認識・翻訳・識別を試す【Python】
この記事では、OpenAIが提供する音声認識モデル「Whisper」を使って、音声認識、音声翻訳、音声識別をPythonコードで実装する方法を解説します。これまで、ESPnet2を用いたテキスト読み上げや文字起こしについての記事をいくつか執筆してきましたが、今回はより高精度でシンプルに使用できる「Whisper v3」に焦点を当てます。Whisperは複雑な設定が不要でありながら、非常に高い精度を実現しており、実用性が高いのが特徴です。
Whisperとは
WhisperはOpenAIの汎用音声認識モデルです。説明をみると、多言語音声認識(multilingual speech recognition)、音声翻訳(speech translation)、言語識別(language identification)ができるモデルだと書いてあります。
今回は、音声認識、音声翻訳、そして、音声識別の3つすべてをPythonで実装してみました。
実験は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'])
"わがはいは猫である 名前はまだないどこで生まれたかとんと 検討がつかぬなんでも薄暗いじめじめしたところでにゃあにゃあ泣いていたことだけは 記憶している"
我が輩がひらがなになったので、音声ファイル名を引数とした場合と挙動が変化したみたいです。ただ、結果は問題なさそうです。
16,000Hzに変換
次は、16000Hzに変換
speech, sr = librosa.core.load("test.wav", sr =16000)
result = model.transcribe(speech)
print(result['text'])
”我が輩は猫である。名前はまだない。どこで生まれたかとんと検討がつかぬ。なんでも薄暗いじめじめしたところでにゃあにゃあ泣いていたことだけは記憶している。”
音声ファイルを直接入力したときと同じ結果になりました。音声ファイルの場合は、内部で適切なサンプリングレートに変換されている感じがします。
Whisperでは、サンプリングレートを変換しなくても認識できるようです(変換した方がよいとは思いますが、実験ではあまり差が出ませんでした)。
まとめ
以上、Whisperを使って、文字起こし、翻訳、言語推定をやってみました。ライブラリの性能が上がってきて本当に簡単にできるようになりました。本当に使い方(アイデア次第)次第です。