まとめ
タイトル通りのシステムを組み実際に動かしてみました。
(最終的にはルンバを動かしました)
音声データが短すぎて(5 秒以下)あまりよい認識精度(~50%)は得られませんでしたが、手元で長い音声データを取って直接 Google Speech API に投げた場合は結構な精度で認識してくれていたので、ちゃんとやればいいところまでいくかもしれません(twilio の無料枠を使い切るのが怖かったため時間を短めに設定していたのが敗因)。
ローカルで音声認識させればもっと簡単に色々できると思いますが、こんなやり方もあるよということで。
システム構成
電話 -> twilio -> GAE -> Google Speech API -> ローカル PC -> roomba
※実際は twilio から GAE には 2 回 POST が飛びます(後述)
- 電話: 普通の電話です
- twilio: 電話の着信や発信などを自動化できるサービス。今回は着信と音声データの保存を担当
- GAE: Google の PaaS。今回は Twilio からの Webhook のハンドリングと音声データを Google Speech API に投げる部分を担当
- Google Speech API: Google 謹製の音声認識サービス。
- ローカル PC: 音声認識結果を元に作られたコマンドデータをポーリングして roomba に色々やらせる。
- roomba: お掃除ロボット。歌ったりしちゃうおちゃめなやつ。
やったこと
コードはこちら。突貫で作ったのでお世辞にも綺麗とは言えないです。
-
twilio にアカウントを作成し、電話番号を取得、Webhook を設定。
-
GAE のコードを作成し(Python)、着電した際の Webhook のハンドラと、音声データの保存が完了した際の Webhook のハンドラを用意。
- 音声データ(.wav)を取得し、適宜変換して Google Speech API に投げる。
- 返ってきた文字列中に指定した文字列が含まれていたらコマンドデータを登録
-
ローカルで動かすサービス(Python)を作成。
- GAE のコマンドデータをポーリング
- コマンドが更新されていたら指示通りルンバを動かす
説明とか
twilio からの Webhook
twilio には TwiML という仕組みがあって、着信時の Webhook に対して適当な XML を返すことで挙動を簡単に制御できます。
例えば、以下のように書くことで「おはようございます」を日本語で読み上げた後、 5 秒間音声データを録音して、録音に成功したら http://hogehoge/record
に対してリクエストを送る、という挙動になります。
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="alice" language="ja-JP">おはようございます</Say>
<Record maxLength="5" action="http://hogehoge/record" />
</Response>
-
Response
は root 要素です、お約束。 - 今のところ
voice="alice"
以外は日本語に対応していません。
録音完了後のリクエストに含まれる RecordingUrl
というパラメータに録音データの保存先が記載されているので、簡単にダウンロードすることができます。
なお、この録音データは WAV
形式で sample rate は 8000 のようです(仕様は見つからず)。
GAE から Google Speech API へのリクエスト
認証をどうすればいいのかドキュメントが見つからず意外と悩みました。結論から言うと GAE サービスの Default Credential を利用すれば OK です(参考)。
from oauth2client.client import GoogleCredentials
# Global Variables
credentials = GoogleCredentials.get_application_default()
...
service = build('speech', 'v1beta1', credentials=credentials)
request = service.speech().syncrecognize(
body={
...
})
response = request.execute()
ただ、この際に利用する oauth2client
はデフォルトでは利用できないので vendoring する必要があります。
必要なライブラリを適当なディレクトリの下に置いて、 appengine_config.py
の中で以下のように指定すれば普通に import
できるようになります。
from google.appengine.ext import vendor
# Add any libraries installed in the "hoge" folder.
vendor.add('hoge')