はじめに
かつて、音声認識と音声合成を組み合わせて遊んでみるという主旨の記事を書いたことがある。
音声合成には、コマンドラインから音声合成できるOpenJTalkパッケージを用いたのだった。これをPythonから動かす場合には、専用の関数を定義して呼び出す必要があり、ひと手間かかる。
最近、山本りゅういち氏がPyOpenJTalkなるパッケージを整備し、単体でTTS(Text-to-Speech、テキストを音声に変換する)機能を実現した。
https://t.co/Fi7L4SSdeq アップデート終了。デモノートブック作りました。hts_engine_API, open_jtalk を事前にインストールしなくても良いように内部的に変更しています。以前はテキスト処理だけでしたが、波形生成の仕組みも入れて、単体でTTSとして遊べるようになりました。
— 山本りゅういち / Ryuichi Yamamoto (@r9y9) March 21, 2021
これを使って前回記事のPythonスクリプトを少しきれいにしたというのが本記事の主旨である。
インストール
音声認識にはSpeechRecognitionパッケージを使う。PyOpenJTalkが今回のキモなので忘れずにインストールする。最新版をインストールするという意味で--upgradeオプションもつけておく。
pip3 install SpeechRecognition
pip3 install --upgrade pyopenjtalk
スクリプト
以下のスクリプトを適当な名前で保存し、実行する。 「話しかけてみましょう!」と表示されたのち、適当な言葉をしゃべると、認識された言葉をオウム返しで音声合成して終了するというシンプルなものである。
import subprocess import numpy as np import pyopenjtalk import speech_recognition as sr from scipy.io import wavfile OUT_WAV = "/tmp/tts.wav" if __name__ == "__main__": # マイクからの音声入力 r = sr.Recognizer() with sr.Microphone() as source: print("話しかけてみましょう!") audio = r.listen(source) try: # 日本語でGoogle音声認識 text = r.recognize_google(audio, language="ja-JP") except sr.UnknownValueError: print("Google音声認識は音声を理解できませんでした。") except sr.RequestError as e: print("Google音声認識サービスからの結果を要求できませんでした;" " {0}".format(e)) else: print(text) # 音声認識結果を音声合成する x, sr = pyopenjtalk.tts(text) # wavファイルに保存 wavfile.write(OUT_WAV, sr, x.astype(np.int16)) # 保存したwavファイルを再生 subprocess.run("afplay " + OUT_WAV, shell=True)
おわりに
PyOpenJTalkのおかげでTTSが手軽に実現でき、楽しい。PyOpenJTalkには話速変換やピッチ変換のオプションもあるので、調べて使ってみるのが良いだろう。
おまけ
話速変換とピッチ変換のオプションを使ったnotebookはこちらから。 nbviewer.jupyter.org
注意点
実行時のエラー
File "pyopenjtalk/htsengine.pyx", line 1, in init pyopenjtalk.htsengine ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject
このようなエラーが出たら、numpyを再インストールしてみるのが吉。
Google音声認識API
ただし、本記事で利用しているGoogle音声認識APIはあくまでテスト/デモ用であり、いつGoogle側にAPI利用を打ち切られても文句は言えない。Google製の音声認識APIを使いたい場合はCould Speech-to-Textの認証情報を取得して使うのが本筋である。ひと月あたり60分の音声までなら利用無料であるが、それ以上を利用するにはお金がかかる。