こんにちは、ネクスト リッテルラボラトリーの清田です。
最近、pepperくんにコンシェルジュ的なことをやらせてみたい、と思って触り始めています。 ただ、pepperくんにデフォルトで搭載されている音声認識エンジンですが、まだまだ精度がいまいちといったところで、pepper開発者の皆さんも苦労されているかと思います。
もちろん、Speech Reco.ボックスで認識させたいことばをすべて登録しておけば精度は出せますが、やはり地名や駅名なども認識させたいところです。
そこで、今回はrospeexというライブラリを使って、クラウド音声認識サービスを使う方法を試してみました。ROS (Robot Operating System)を利用しています。
詳しい利用方法についてはQiitaに書いていますので、そちらをご覧ください。
クラウド音声認識サービスとは?
認識したい音声を含む信号データをAPI経由でサーバーに送ると、認識結果をテキストで返してくれるサービスです。 SiriやAndroidの音声認識機能でも、認識処理はサーバー側で行われているようです。
Google Web Speech API Demonstration のページでは、Google Speech APIによる音声認識を試してみることができます。
とくに固有名詞(地名や会社名など)の認識精度には驚く方も多いのではないでしょうか? 噂では、深層学習 (Deep Learning)が使われているのではないかといわれています。
また、情報通信研究機構 (NICT)も、rospeexを通して利用できる音声認識サービスを公開しています。 こちらは、日本語・英語・中国語・韓国語の4カ国語に対応しています。
pepperくんのマイク信号をネットワーク経由でキャプチャする
NAOqiのライブラリに入っているALAudioDeviceを使うと、ネットワーク経由でpepperくんのマイク信号を取得したり、pepperくんのスピーカーに出力したりできます。
APIドキュメントによれば、マイク信号には「front, rear, left, right」の4チャンネルが含まれていて、サンプリング周波数はそれぞれ16000Hzになっているようです。
今回は、ROSのパッケージ naoqi_sensors に含まれているmicrophone.py を利用してマイク信号をドライブします。
「話しているところ」だけをどうやって抽出するか?
マイクで取得した音声信号をすべてクラウド側に送ってしまうと、あっという間に接続制限を食らってしまいます。
そこで、音声信号の中から「話しているところだけ」を抽出する処理が必要になります。
今回は、とりあえずマイク信号の二乗平均平方根をとって、エネルギー値が閾値を上回る箇所を抽出する方法を利用しました。 Python SpeechRecognitionモジュールの処理を参考にして、audioopモジュールを用いています。
どれくらいの精度で認識できるか?
きちんと実験できているわけではありませんが、認識エンジンにGoogleのものを使うと、Androidの音声認識機能とほぼ同じ結果が得られるようです。
NICTのエンジンについても、pepperくん搭載のエンジンよりはかなりよい結果を得られる感じです。
TODO
というわけで、クラウド音声認識サービスで「pepperくんの耳を良くする」方法を紹介しました。
ただ、実用的に使うにはまだいくつかの課題があります。
APIの利用制限
Google Speech APIは非常に良い精度で認識してくれるのですが、利用回数の制限(公式には1日50回まで)が設けられているため、実験用途以外の利用は厳しそうです。ビジネス向けの有償サービスの開始を期待しましょう。
NICTのAPIは、利用回数の制限こそないものの、無償利用は学術研究目的に限定されています。有償ライセンスを購入すると、商用利用が可能です。
「話しているところ」の抽出にもう一工夫が必要
今回は、とりあえずの実装として二乗平均平方根によるエネルギー値の計算を使いましたが、人間の声以外の物音も拾ってしまうため、うるさい場所では無駄なAPIコールが多数発生してしまいます。
人間の声だけを抽出するためには、Voice activity detectionなども試した方がよさそうです。
話しおわってから認識結果を得るまでに時間がかかる
今回の実装では、話しおわった箇所を検出し、音声信号のデータを全部作成してからAPIに送っているため、認識結果を得るまでに数秒のタイムラグが発生しています。
話しはじめたことを検出した時点からサーバーに音声信号データを送り始めることで、認識結果を得るまでの時間を短縮できると思います。