以前の記事でOpenAIが開発した音声認識モデル「Whisper」をRaspberry Piにインストールして音声認識を試しました。
今回は、Raspberry Piに接続した「USBマイクの音声」をWhisperに渡して文字に起こします。
試した環境は以下です。
- Raspberry Pi 4
- Linux raspberrypi 5.15.84-v8+ #1613 SMP PREEMPT Thu Jan 5 12:03:08 GMT 2023 aarch64 GNU/Linux
- Python 3.9.2
- PyAudio 0.2.11
マイク音声をWhisperで文字に起こすまでの流れ
以下がマイク音声を文字に起こすまでの流れです。
- Raspberry PiにUSBマイクを接続する
- PyAudioでRaspberry Piのマイク音声を録音する
- 録音した音声をWhisperの音声認識で文字に起こす
Raspberry Piに接続したマイクの音声をテキストに変換します。
Raspberry PiにUSBマイクを接続する
まずRaspberry PiにUSBマイクを接続します。
USBマイクは以下を使用しました。
注意点としてRaspberry Pi 4の3.5mm 4極ジャックではマイク入力を扱えないようです。
昨今、USBマイクはあまり見かけませんが、今回は以下のマイクをAmazonで購入して使用しました。
これをRaspberry Pi 4のUSB 2.0端子(端子の一部が白い方)に接続しました。
PyAudioでマイク入力を録音する
次にPyAudioをインストールします。
PyAudioは音声を扱うためのPythonライブラリです。
PortAudioという音声のライブラリをPython用にラップしたものです。
今回はこれを使ってマイクの音声を取得して保存します。
PyAudioは以下のコマンドでインストールできます。
sudo apt install python3-pyaudio
マイクを接続してインデックスを調べる
次に、接続したマイクがRaspberry Piでどのように認識されているかを調べます。
ここで得られる情報(マイクのインデックス)が後ほど音声を録音する際に必要になります。
USBマイクをRaspberry Piに接続してから以下を実行します。
from pprint import pprint
import pyaudio
p = pyaudio.PyAudio()
for i in range(p.get_device_count()):
pprint(p.get_device_info_by_index(i))
上記を実行すると接続されているデバイスの一覧が表示されるので、接続したマイクの情報を探します。
接続したマイクがどれかわからない場合は、マイクを接続したときと外したときのそれぞれでコードを実行して比較しましょう。マイクを接続したときに増えた分がUSBマイクの情報です。
例として今回接続したUSBマイクの情報を抜粋します。
...(略)
{'defaultHighInputLatency': 0.034829931972789115,
'defaultHighOutputLatency': -1.0,
'defaultLowInputLatency': 0.008684807256235827,
'defaultLowOutputLatency': -1.0,
'defaultSampleRate': 44100.0,
'hostApi': 0,
'index': 1, # これが今回欲しい情報(マイクのインデックス)
'maxInputChannels': 1,
'maxOutputChannels': 0,
'name': 'USB Microphone: Audio (hw:3,0)',
'structVersion': 2}
nameが「USB Microphone Audio (hw:3,0)」
となっています。
これが今回接続したマイクです。
先程のコードで使用した関数 get_device_info_by_index の戻り値は、PortAudioの「PaDeviceInfo」という型を反映した辞書型になっています。
この中の「index」というキーに紐付いている値がマイクの「インデックス」です。
これを覚えておきます。
ここでは 'index': 1
とあるので、インデックスは「1」です。
USBマイクの音声を録音する
マイクのインデックスが特定できたら、いよいよ録音します。
PyAudioのドキュメントに従って以下のコードを書きます。
変数dev_index
に先ほど調べたマイクのインデックスを入れます。
import wave
import sys
import pyaudio
CHUNK = 4096 # 1度にどれくらい音を録るか
FORMAT = pyaudio.paInt16
CHANNELS = 1 # モノナルなら1、ステレオなら2。今回はラズパイなので1
RATE = 44100 # サンプリングレート
RECORD_SECONDS = 3 # 録音する秒数
DEV_INDEX = 1 # デバイスのインデックス
with wave.open('output.wav', 'wb') as wf:
p = pyaudio.PyAudio()
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
stream = p.open(
format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
input_device_index=DEV_INDEX
)
print('Recording...')
for _ in range(0, RATE // CHUNK * RECORD_SECONDS):
wf.writeframes(stream.read(CHUNK, exception_on_overflow = False))
print('Done')
stream.close()
p.terminate()
はじめにPythonのwaveモジュールを使ってwavファイルを作成します。
そしてPyAudioを使ってマイク音声(stream)を取得してwavファイルに書き込みます。
以上のコードを実行して「Recording…」が表示されたら、マイクに向かって何か話してみましょう。
3秒後には「output.wav」というファイルに音声が記録されているはずです。
無事に「output.wav」が作成できていたら再生してみましょう。
aplayコマンド(ALSA)でwavファイルを再生できます。
aplay output.wav
録音したマイク音声をWhisperで認識して文字に起こす
さて、今回の目標はマイク音声をWhisperで認識して文字に起こすことです。
Raspberry PiでWhisperを使って音声認識する方法は以前の記事で詳しく書いているので参照してください。
今回は先ほどのコードにWhisperによる音声認識のコードを追記しました。
import wave
import sys
import pyaudio
CHUNK = 4096 # 1度にどれくらい音を録るか
FORMAT = pyaudio.paInt16
CHANNELS = 1 # モノナルなら1、ステレオなら2。今回はラズパイなので1
RATE = 44100 # サンプリングレート
RECORD_SECONDS = 3 # 録音する秒数
DEV_INDEX = 1 # デバイスのインデックス
with wave.open('output.wav', 'wb') as wf:
p = pyaudio.PyAudio()
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
stream = p.open(
format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
input_device_index=DEV_INDEX
)
print('Recording...')
for _ in range(0, RATE // CHUNK * RECORD_SECONDS):
wf.writeframes(stream.read(CHUNK, exception_on_overflow = False))
print('Done')
stream.close()
p.terminate()
### (追記)Whisperで文字起こし
import time
import whisper
print('Loading model...')
model = whisper.load_model("tiny") # モデルを指定する
print('Transcribing...')
result = model.transcribe("output.wav", verbose=True, language="ja") # 音声ファイルを指定する
print(result["text"]) # 認識結果を出力
PyAudioで録音した音声ファイル(output.wav)をそのままWhisperに渡しているだけです。
Raspberry PiでWhisperの巨大なモデルを実行すると時間がかかるため、最も小さいモデルである「tiny」を使用します。
また、model.transcribe
の引数でlanguage="ja"
のように言語を指定しています。
これによって、Whisperの言語推定の処理が省略されるため、実行時間を短縮できます。
マイク入力の音声認識を試す
以上のコードを実行し「Recording…」が出力されている間に日本語で何かを話すと、PyAudioが音声を録音して、それをWhisperが文字に起こします。
今回使用したのはWhisperのtinyモデルのため、文字起こしの精度はいまいちですが「今日の天気は?」や「おはようございます」などの一般的な日本語であれば正確に文字に起こしてくれます。
まとめ
今回はRaspberry Piに接続したマイクの音声をWhisperに入力して文字起こしを試しました。
マイク音声に対する文字起こしの精度はそれほど高くありませんが、使えないというほどでもなく、用途を絞れば面白いものが作れそうでした。
次回は、音声から変換したテキストをRaspberry Piでオウム返しするように読み上げさせる予定です。
記事の内容にわからないことがある方は以下のアカウントに気軽にDMしてください!
また、最新の技術の活用方法など役に立つツイートを心がけているので、ぜひフォローしてもらえると嬉しいです!