次のように設定しました
・Raspberry Pi2に「jtalk」と「WiringPi」をインストール。設定は省略します。
本ホームページの「Raspberry Piを使って、音声命令でキャタピラを操作」を参照してください。
・Google からSpeech API key を取得。
・Google音声認識API を使って、雑談対話を試す。
・雑談対話の返事を「jtalk」の「メイちゃん」の声で応答させる。
1.NTTDocomoの音声認識APIは、以下の2通りがあります。
(1)「Powered by NTTテクノクロス」・・・Androidで提供
(2)「Powered by アドバンスト・メディア」・・・REST形式で提供
前回の「OpenJtalkと+NTTdocomo音声認識・雑談会話APIをつかって会話を楽しむ(2)」
では②の音声認識「Powered by アドバンスト・メディア」を使って雑談対話を試してみましたが、
APIキーは利用期間が90日間の制限があります。
そこで、Googleの音声認識API「Speech API」を使って、NTTdocomo雑談会話を試みてみたいと
思います。
2.Googleの音声認識API「Speech API」の使用料金及び音声エンコードは次のようになっています。
前回の「OpenJtalkと+NTTdocomo音声認識・雑談会話APIをつかって会話を楽しむ(2)」では、
「.wave」ファイル形式を使っていましたので、
今回、音声ファイルは「.FLAC」ファイル形式を使用し、メタデータを格納するヘッダーが
含まれている必要があります。
そこで書籍「自然会話ロボットを作ろう!」を参考させてもらい、音声処理ライブラリ「sox」を
使うことにしました。
事前のソフト及びアンプの回路等は、前のページ「(2)Pythonプログラムを作成し雑談対話を試す」
と同じです。
1.soxライブラリをRaspberry Piにインストール。
ターミナルで次のように入力しインストールします。
$ sudo apt-get install alsa-utils sox libsox-fmt-all
2.音声入出力のカード番号等については、他のページ「Raspberry Piを使って、音声命令で
キャタピラを操作(1)」と同様ですので参照してください。
再掲しますと、
(1)音声入力カード番号は、ターミナルで、「 $ arecord -l 」と入力し確認します。
(2)音声出力のカード番号は、同様にターミナルで、「 $ aplay -l 」と入力し
確認します。
3.音声入力のテスト
(1)ターミナルで次のように入力し、5秒以内でマイクロフォンに向かって話して音声入力の
テストをします。
$ AUDIODEV=hw:1 rec -c 1 -r 11025 speak.flac trim 0 5
・AUDIODEV=hw:1 は、音声入力デバイスで、カード番号が1。
・-c は、音声チャンネル数で、1はモノラル。
・-r は、サンプリングレートで、11025は11025Hz。
・speak.flac は、出力先の音声データファイル。
・trim は、音声入力時間で、0 5は、入力時間が5秒。
(2)音声入力データの確認
ターミナルで次のように入力して、録音したデータを再生し、スピーカーから
聞こえたらOKです。
$ play speak . flac
1.「listen . py」のプログラムは、次のようにしました。
# python listen.py #!/usr/bin/env python # -*- coding: utf-8 -*-
import sys import os import time import requests import json PATH = '/home/pi/speak.flac' GOOGLE_APIKEY = 'Google Speech-APIキー' url_v ='https://www.google.com/speech-api/v2/recognize?xjerr=1&client=chromium&lang=ja-JP& maxresults=10&pfilter;=0&xjerr=1&key=' + GOOGLE_APIKEY hds = {'Content-type': 'audio/x-flac; rate=11025'} os.system("gpio -g mode 7 out") def recognize(): files = open(PATH, 'rb') voice = files.read() files.close() try: rsp = requests.post(url_v, data=voice, headers=hds).text except IOError: return '#CONN_ERR' except: return '#ERROR' objs = rsp.split(os.linesep) for obj in objs: if not obj: continue alternatives = json.loads(obj)['result'] if len(alternatives) == 0: continue return alternatives[0]['alternative'][0]['transcript'] return '' os.system("/home/pi/jtalk.sh 会話を始めます") while True: os.system("gpio -g write 7 1") os.system("AUDIODEV=hw:1 rec -c 1 -r 11025 " + PATH + " trim 0 5") os.system("gpio -g write 7 0") message = recognize().encode('utf-8') if (message == '#CONN_ERR'): print 'internet not available' message = '' elif (message == '#ERROR'): print 'voice recognizing failed' message = '' else:
print 'your word:' + message if message == "": print "クライアントの実行を停止します" os.system("/home/pi/jtalk.sh 会話を終了します") break
2.動作は、次のようになります。
(1)起動後、「メイちゃん」の声で、スピーカーから「会話を始めます」と聞こえます。
(2)それと同時に、アンプに設置している青のLEDが点灯します。青のLEDが点灯したら
マイクに向かって話します。
(3)青のLEDが消灯したら音声入力は終了です。5秒間の間に話します。
(4)画面に話した内容が表示されます。
(5)再度、青のLEDが点灯しますので、マイクに向かって話します。これの繰返しです。
(6)青のLEDが点灯しているときに、何も話さない(無音)と、画面に「クライアントの
実行を停止します」と表示され、
「メイちゃん」の声で、スピーカーから「会話を終了します」と聞こえます。
そしてプログラムは、break します。
3.「listen . py」を実行した結果が次の画面です。(Python2 IDEを使用)
Google Speech APIが何とか動いています。
プログラム中の「jtalk.sh」は、シェルスクリプトで、他のページ「Raspberry Piを使って、
音声命令でキャタピラを操作(1)」に記していますので確認してください。
1.雑談会話のプログラム「zatudan.py」は次のようにしました。
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import time import requests import json PATH = '/home/pi/speak.flac' DOCOMO_APIKEY= 'NTTDocomo-雑談対話APIキー' GOOGLE_APIKEY = 'Google Speech-APIキー' url_z = 'https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=%s'%(DOCOMO_APIKEY) url_v ='https://www.google.com/speech-api/v2/recognize?xjerr=1&client=chromium&lang=ja-JP& maxresults=10&pfilter=0&xjerr=1&key=' + GOOGLE_APIKEY hds = {'Content-type': 'audio/x-flac; rate=11025'} modeID = "" contextID = "" os.system("gpio -g mode 7 out") def recognize(): files = open(PATH, 'rb') voice = files.read() files.close() try: rsp = requests.post(url_v, data=voice, headers=hds).text except IOError: return '#CONN_ERR' except: return '#ERROR' objs = rsp.split(os.linesep) for obj in objs: if not obj: continue alternatives = json.loads(obj)['result'] if len(alternatives) == 0: continue return alternatives[0]['alternative'][0]['transcript'] return '' def dialogue(message): global contextID, modeID userload = { "utt": message, "context":contextID, "nickname": "椋", "nickname_y": "ムク", "sex": "男", "bloodtype": "A", "birthdateY": "1997", "birthdateM": "1", "birthdateD": "16", "age": "30", "constellations": "水瓶座", "place": "横浜", "mode": modeID, "t": "" } r = requests.post(url_z, data=json.dumps(userload)) print ("Mei: "), print r.json()['utt'] modeID = r.json()['mode'] contextID = r.json()['context'] return r.json()['utt'] os.system("/home/pi/jtalk.sh 会話を始めます") while True: os.system("gpio -g write 7 1") os.system("AUDIODEV=hw:1 rec -c 1 -r 11025 " + PATH + " trim 0 5") os.system("gpio -g write 7 0") message = recognize().encode('utf-8') if (message == '#CONN_ERR'): print 'internet not available' message = '' elif (message == '#ERROR'): print 'voice recognizing failed' message = '' else: print 'your word:' + message if message == "": print "クライアントの実行を停止します" os.system("/home/pi/jtalk.sh 会話を終了します") break talkmessage = dialogue(message) os.system("/home/pi/jtalk.sh " + talkmessage.encode('utf-8')) time.sleep(5)
2.雑談会話のプログラム「zatudan.py」の実行結果は次の通りになります。
(Python2 IDEを使用)
画面だけでなくスピーカーから「Meiちゃん」の声で応答があります。
雑談対話は、こちらが質問すると話が飛んでしまい、そのうち質問ばかりに
なってきて、こちらが答える形になってしまいます。
しかたないのかな?