Twilioの音声をMicrosoftのBing Speech APIを使ってテキスト化する方法
マインドテックの冨です。
先日、Twilioのハッカソンに行ってきました。電話を使ったアプリケーションを作ろうとすると、音声をテキスト化したいニーズが出てきます。実際、Twilioにはテキスト化の機能もあるのですが、現状では日本語は対象外なんですよね。(あとテキスト化のお値段がちょっと高いw)
そんなわけでテキスト化するためには(自力で実装するのでなければ)外部のAPIを呼び出す必要があります。Google Speech APIを利用する方法は昔、高橋さんがガッツリ書いておられるので、ここではBing Speech APIを利用する方法をご紹介しましょう。サンプルはpython2.7で動作確認をしていますが、もちろん他の言語でも問題ないと思います。
ドキュメントと関連リンク
Bing Speech APIとは
https://azure.microsoft.com/ja-jp/services/cognitive-services/speech/
ドキュメント
https://www.microsoft.com/cognitive-services/en-us/speech-api/documentation/overview
Speech APIではテキスト化する音声認識と、テキストを音声データに変換する機能がありますが、ここでは前者を使います。
Microsoft Congitive Serviceのアカウントは取得しておいてください。
https://www.microsoft.com/cognitive-services/en-us/
APIキーの取得
Cognitive Service の管理画面で"Bing Speech"のサービスの箇所から"key 1″をShow/Copyしておいてください。API呼び出しの際に必要になります。
認証~APIアクセストークンの取得
APIの呼び出しの際には認証が必要になります。詳細はドキュメントを参照いただくとして(笑)キーを送って認証トークンを取得します。トークンは10分間有効。
リクエストヘッダー"Ocp-Apim-Subscription-Key"にAPIキーを指定します。
Pythonでこんな感じに書きました。requestsを使ってます。
[python]
import requests
import urllib
def authorize():
url = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"
headers = {
"Content-type": "application/x-www-form-urlencoded",
"Ocp-Apim-Subscription-Key": "取得したAPIキー"
}
response = requests.post(url, headers=headers)
if response.ok:
_body = response.text
return _body
else:
response.raise_for_status()
[/python]
音声変換
先に取得したアクセストークンは、API呼び出しの際にヘッダーに付与します。
"Authorization": "Bearer " + token
認証の場合と同様に、指定されたエンドポイントにPOSTでデータを投げます。
[python]
import requests
import urllib
def speech_to_text( raw_data, token, lang="ja-JP", samplerate=8000, scenarios="ulm"):
data = raw_data
params = {
"version": "3.0",
"requestid": "b2c95ede-97eb-4c88-81e4-80f32d6aee54",
"appid": "D4D52672-91D7-4C74-8AD8-42B1D98141A5",
"format": "json",
"locale": lang,
"device.os": "Windows",
"scenarios": scenarios,
"instanceid": "565D69FF-E928-4B7E-87DA-9A750B96D9E3" # from Sample Bot Framework
}
url = "https://speech.platform.bing.com/recognize?" + urllib.urlencode(params)
headers = {"Content-type": "audio/wav; samplerate={0}".format(samplerate),
"Authorization": "Bearer " + token }
response = requests.post(url, data=data, headers=headers)
if response.ok:
result = response.json()["results"][0]
return result["lexical"]
else:
raise response.raise_for_status()
[/python]
“version","appid"などは指定された固定値。
“requestid","instanceid"は本当はGUIDを作成しなければいけないようですが、サンプルの文字列で動いたのでそのまま使っています(笑)きちんとしたい人は適当に直してください。
“senario"もulm, websearch などの指定が出来るようですが、違いがよく分かりませんでした。スミマセン。
端末でのテスト
これらを呼び出して実際にテキスト化してみます。適当に声を録音したwavファイルを作成します。(サンプリングレートは8000にしています。)
[python]
infile = open("sample.wav", 'r’)
raw = infile.read()
txt = speech_to_text( raw , token, lang="ja-JP", samplerate=8000, scenarios="ulm")
print "text : " + txt
[/python]
これで
$ python test.py text : こんにちは
こんな感じで表示されば、呼び出しはうまくいっています。
Twilioの録音音声を上記の例の"sample.wav"に相当するデータとして引き渡しできればOKです。
サーバー側のアプリ
続いて、TwiMLを返し、録音音声を取得して先のSpeech APIを呼び出すWebアプリを作成します。電話口で話した言葉をおうむ返しに読み返してくれます。
ここではpythonのBottleフレームワークを利用して、先に作成した関数も組み込んでみます。
[python]
# coding: utf-8
import sys
import os
import bottle
import requests
import urllib
import json
import commands
from bottle import route, run, post, Response, request, static_file
from twilio import twiml
from twilio.rest import TwilioRestClient
reload(sys)
sys.setdefaultencoding('utf-8’)
app = bottle.default_app()
twilio_client = TwilioRestClient('TwilioのACCOUNT SID’ , 'TwilioのAUTH TOKEN’)
TWILIO_NUMBER = os.environ.get('(TWILIO_NUMBER)’, '(Twilioで購入した電話番号)’)
NGROK_BASE_URL = os.environ.get('NGROK_BASE_URL’, ")
@route('/’)
def index():
"""Returns standard text response to show app is working."""
return Response("Bottle app up and running!")
@post('/twiml’)
def twiml_response():
response = twiml.Response()
response.say("何か話してキーを押してください。",language="ja-jp",voice="woman")
response.record(action="http://(サーバーのアドレス)/handlerecording",method="GET", maxLength="20", finishOnKey="0123456789*#")
return Response(str(response))
@route('/handlerecording’)
def handlerecording():
recording_url = request.query.get('RecordingUrl’)
voice = urllib.urlopen(recording_url).read()
## Authorize for Bing Speech API
token = authorize()
txt = speech_to_text( voice , token, lang="ja-JP", samplerate=8000, scenarios="ulm")
# respond TwiML
response = twiml.Response()
response.say(txt,language="ja-jp",voice="woman")
return Response(str(response))
def authorize():
url = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"
headers = {
"Content-type": "application/x-www-form-urlencoded",
"Ocp-Apim-Subscription-Key": "(API key)"
}
response = requests.post(url, headers=headers)
if response.ok:
_body = response.text
return _body
else:
response.raise_for_status()
def speech_to_text( raw_data, token, lang="ja-JP", samplerate=8000, scenarios="ulm"):
data = raw_data
params = {
"version": "3.0",
"requestid": "b2c95ede-97eb-4c88-81e4-80f32d6aee54",
"appid": "D4D52672-91D7-4C74-8AD8-42B1D98141A5",
"format": "json",
"locale": lang,
"device.os": "Windows",
"scenarios": scenarios,
"instanceid": "565D69FF-E928-4B7E-87DA-9A750B96D9E3" # from Sample Bot Framework
}
url = "https://speech.platform.bing.com/recognize?" + urllib.urlencode(params)
headers = {"Content-type": "audio/wav; samplerate={0}".format(samplerate),
"Authorization": "Bearer " + token }
response = requests.post(url, data=data, headers=headers)
if response.ok:
result = response.json()["results"][0]
return result["lexical"]
else:
raise response.raise_for_status()
if __name__ == '__main__’:
run(host=’(サーバーのアドレス)’, port=80, debug=False, reloader=True)
[/python]
(Twilioサーバー側の録音音声を削除する機能を入れてませんので、必要に応じて追加してみてください。)
TwiML取得URLの設定
Twilioコンソールで購入した電話番号の、TwiML取得URLを設定します。
電話番号>アクティブな電話番号>音声通話の"A CALL COMES IN"の欄を、上記のBottleアプリが動いているサーバーを指定します。
ここまでで作業は終了です。購入した電話番号に電話をかけて、ガイダンスに従って何かを話、任意のボタンを押すと、裏では”Bing Speech API"を呼び出してテキスト化し、それをTwiMLのSay動詞で読み上げを行います。上記のサンプルでお分かりの通り、Twilioの録音音声をそのまま読み込んで、Speech APIに渡せばテキスト化されてきます。特に変換は必要ありませんでした。
取得したテキストは何らかの処理に使えると思いますので、工夫してアプリを作ってみてください。(自分は同じMicrosoftのLUIS(language Understanding Intelligent Service)に送って意味解析をさせる事をやってみました。これについては改めて書こうと思います。)
ではでは。