Pythonを使用したリアルタイム音声文字起こしの手順[SpeechRecognitionとPyAudioを活用した音声認識]

前回は、Waveファイルに起こしたデータの文字起こしに挑戦してみましたが、今回はリアルタイムでマイク音声 文字起こしする方法に挑戦してみましたので、その方法についてシェアいたします。

今回は、前回までに記事にした二つの合わせ技でリアルタイム文字起こし環境を作成しています。
今回の記事内にURLを張り付けておくので興味ある方はそちらを見てみてください。

使用ライブラリ

まずは、今回のプログラムに必要なライブラリです。

  • pyaudio
  • speech_recognition

今回のライブラリはすでにインストール済みですので、すいませんが、画像はありません。
インストールには以下のコマンドを入力することでインストール可能です。

pip install XXX

※XXXに上記のライブラリ名を入れてください。

プログラムと実行結果

ではいつも通りプログラムの全体です。

import time
import speech_recognition
import pyaudio

SAMPLERATE = 44100

def callback(in_data, frame_count, time_info, status):
    global sprec 
    try:
        audiodata = speech_recognition.AudioData(in_data,SAMPLERATE,2)
        sprec_text = sprec.recognize_google(audiodata, language='ja-JP')
        print(sprec_text)
    except speech_recognition.UnknownValueError:
        pass
    except speech_recognition.RequestError as e:
        pass
    finally:
        return (None, pyaudio.paContinue)
    
def main():
    global sprec 
    sprec = speech_recognition.Recognizer()  # インスタンスを生成
    # Audio インスタンス取得
    audio = pyaudio.PyAudio() 
    stream = audio.open( format = pyaudio.paInt16,
                        rate = SAMPLERATE,
                        channels = 1, 
                        input_device_index = 1,
                        input = True, 
                        frames_per_buffer = SAMPLERATE*2, # 2秒周期でコールバック
                        stream_callback=callback)
    stream.start_stream()
    while stream.is_active():
        time.sleep(0.1)
    
    stream.stop_stream()
    stream.close()
    audio.terminate()
    

    
if __name__ == '__main__':
    main()

実行結果は以下です。
プログラムを実行して、声をマイクに入力したところです。

続いてはプログラムの解説ですが、解説は次ページにて記載します。

プログラム解説

このプログラムでは以下のような流れで処理を行っています。

  1. speech_recognitionのRecognizerインスタンスを取得
  2. PyAudioインスタンスを取得してマイク入力状態にする
  3. 文字起こし処理(PyAudioのコールバックによる処理)
  4. 後処理

前回、記事にした音声入力のコールバック処理で音声認識を一定周期事に行うようにしています。

speech_recognitionのRecognizerインスタンスを取得

これは簡単です。コードとしては以下だけです。
コールバックの中でこのインスタンスを使用したいので、グローバルとしています。
これは、コールバックの中でインスタンスを生成してもいいですが、そうする場合コールバック内でインスタンスの生成が毎回行われて無駄なので、グローバルとして定義しています。

    global sprec 
    sprec = speech_recognition.Recognizer()  # インスタンスを生成

PyAudioインスタンスを取得してマイク入力状態にする

続いて、マイク入力の開始処理です。
以下がその処理該当します。
流れ的には、前回の正弦波音声出力とほぼ同じです。
違うところは、基本的にaudio.openのパラメータをoutputからinputに変更しているだけです。
frames_per_bufferは、コールバックが来る周期となります。
今回は、2秒周期くらいで処理するのが適切と思いますので、サンプリングレート*2の2秒で設定しています。
※サンプリングレートは、1秒間にどれだけサンプリングするかのこと
また、処理行うためのコールバック関数は、callbackという名前の関数を設定しています。

# Audio インスタンス取得
    audio = pyaudio.PyAudio() 
    stream = audio.open( format = pyaudio.paInt16,
                        rate = SAMPLERATE,
                        channels = 1, 
                        input_device_index = 1,
                        input = True, 
                        frames_per_buffer = SAMPLERATE*2, # 2秒周期でコールバック
                        stream_callback=callback)
    stream.start_stream()
    while stream.is_active():
        time.sleep(0.1)

具体的な内容を知りたい方は、以下を参照してください。

文字起こし処理(PyAudioのコールバックによる処理)

では実際の文字起こし処理です。
この関数は、2秒周期でpyaudioから入力データが通知されてきます。
あとは、speech_recognitionのAPIを呼び出しし文字起こしをしています。

def callback(in_data, frame_count, time_info, status):
    global sprec 
    try:
        audiodata = speech_recognition.AudioData(in_data,SAMPLERATE,2)
        sprec_text = sprec.recognize_google(audiodata, language='ja-JP')
        print(sprec_text)
    except speech_recognition.UnknownValueError:
        pass
    except speech_recognition.RequestError as e:
        pass
    finally:
        return (None, pyaudio.paContinue)

では、以下で簡単にですが、speech_recognitionの使い方を記載しておきます。

speech_recognitionでは、まず認識を行う対象のAudioDataインスタンスを生成し、それを認識用のAPIで認識させます。

AudioDataインスタンスの生成は、speech_recognition.AudioDataで処理を行います。
これは、第1引数にAudioデータ(bytes)、第2引数にサンプリングレート、第3引数にサンプルサイズ(データのサイズ)を指定すれば、インスタンスを返してくれます。

あとは認識処理ですが、こちらはsprec.recognize_googleで処理を行います。
第1引数には 先ほど生成したAudioDataインスタンス 第2引数には言語を指定しています。
注意点
sprec.recognize_googleAPIは、音声データがないデータを入力すると、エラーで返すようです。
ですので、今回はtry-exceptで、エラーとなった場合に処理しないようにしてあります。

Waveファイルの音声文字起こしをしたいって方は、以下で記事にしていますのでこちらを見てみて下さい。

後処理

最後は後処理です。
最後は、動作状態にしてるStreamの停止処理と今回生成したインスタンス類の破棄をして終了です。
※といっても今のプログラムでは、強制終了しか落とせないので、ここまでこないですが。。。

    stream.stop_stream()
    stream.close()
    audio.terminate()

まとめ

今回は、リアルタイムでのマイク入力音声の文字起こしに挑戦してみましたがいかがだっでしょうか?
実は、今回は簡単にできるだろうと思ってはじめたんですが、注意点で記載した音声入力がないデータをいれるとエラーとなることを知らなかったために、エラーの原因が分からずかなり苦戦しました。
分かってしまえば実に簡単なことで拍子抜けしましたが・・・

あと一点このプログラムには問題があります。
今の処理では、音声の入力タイミングが分からず、ライブラリに渡すデータの音声が途切れるタイミングが出てきて、正しく認識してくれない時があります。
これの解決方法がわかっていませんので、ぜひみなさんで今回の記事を参考に考えてみてください。

最後に、Pythonの基礎を学びたい方は以下がおすすめです。私も持っていてたまに眺めて勉強していますものですのでぜひ購入して学習してみてください。

にいやん

出身 : 関西 居住区 : 関西 職業 : 組み込み機器エンジニア (エンジニア歴13年) 年齢 : 38歳(2022年11月現在) 最近 業務の効率化で噂もありPython言語に興味を持ち勉強しています。 そこで学んだことを記事にして皆さんとシェアさせていただければと思いブログをはじめました!! 興味ある記事があれば皆さん見ていってください!!