Google Speech API ver.2の使い方


## はじめに

Google音声認識のAPは、Version1まではそこら中に、使い方やサンプルスクリプトが転がっていたが、Version2から登録制になったからか、まとまった使い方がどこにも載っていないので、まとめておく。

## 登録からSpeech APIの有効化、APIキーの入手まで

GoogleのSpeech APIは、v1が廃止され、v2になっている。v2からは、登録制になっており、Google APIsのコンソール画面から操作を行う必要がある。以下が登録の手順である。

1. Google APIs Consoleに自分のGoogleアカウントでログインする
	* https://console.developers.google.com/project
1. 左に列挙されているタブの中から「Projects」を選ぶ
1. 「Create Project」のボタンを押し、適当なプロジェクト名を入力して、プロジェクトを新規作成する
1. 右下にアクティビティウィンドウが表示され、プロジェクトの作成が始まる。しばらくすると、作成が終わり、Project Dashboardが開く
1. 左のタブの中から、「APIs & auth」⇒「APIs」を選ぶ。操作可能なAPIのリスト（Browse APIs）が表示されるので、下から、数えて10番目前後にSpeech APIがあるので、右側にある「Off」ボタンを押す。
1. Enabled APIsの中にSpeech APIが追加されているのを確認する
1. 左のタブの中から、「APIs & auth」⇒「Credentials」を選ぶ。
1. OAuthというタイトルから、「Create new Client ID」というボタンを押し、チェックボックスから、Web applicationを選択肢、AUTHORIZED JAVASCRIPT ORIGINSのテキストボックスの中の「https://www.example.com」という文字列を消す。（セキュリティ的には甘くなるので、使うサイトが決定している場合は、そのサイトのドメインを指定すること）
1. Create CliendIDというボタンを押す
1. OAuthの右側にClient ID for web applicationという項目が追加される
1. 下のPublic API accessというタイトルから、Create new Keyというボタンを押し、表示されるボタンの中から、Browser keyを選択する
1. ACCEPT REQUESTS FROM THESE HTTP REFERERS(WEB SITES)というテキストボックスの内容を空（デフォルトのまま）にして、Createボタンを押す
1. Public API accessの右側にKey for browser applicationsという項目が追加される
1. 項目中、API KEYがSpeech APIで使用するキーとなる

## 使い方

上記で取得したキーを使ってポスト命令を以下のURLに送ることで、Google音声認識の結果を受け取ることが出来る。

* https://www.google.com/speech-api/v2/recognize?xjerr=1&client=chromium&lang=ja-JP&maxresults=10&pfilter=0&xjerr=1&key=<取得したAPI Key>

ポスト命令で送るパラメータは、16kのビットレートのflac形式の音声ファイルである。wavでないので、注意すること。結果はjsonで返され、hypothesesというキーに音声認識の結果が尤度とともにリストに入っている。

なお、一つのプロジェクト毎にGoogleの音声認識は50 callsしか許されていない（実際は500 callsほど大丈夫なようである）。が、上記の手順で新しいプロジェクトを作り直し、新規に作成したAPI-Keyに切り替えると、復活する。

以下にpythonでgoogle speech api v2にアクセスするためのサンプルコードを示す。

```stt.py
import sys
import os
import urllib2
import json
import commands

apikey = "ENTER YOUR API KEY"


def stt_google_wav(filename):
    base, ext = os.path.splitext(filename)
    sox_command_template = "sox %s -r 16000 %s.flac"
    command = sox_command_template % (filename, base)
    status, output = commands.getstatusoutput(command)
    if status:
        print output
        return
    f = open(base + '.flac', 'rb')
    flac_cont = f.read()
    f.close()

    googl_speech_url = 'https://www.google.com/speech-api/v2/recognize?xjerr=1&client=chromium&lang=ja-JP&maxresults=10&pfilter=0&xjerr=1&key=' + apikey
    hrs = {
        "User-Agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7",
        'Content-type': 'audio/x-flac; rate=16000'
    }
    req = urllib2.Request(googl_speech_url, data=flac_cont, headers=hrs)
    p = urllib2.urlopen(req)

    raw = p.read()
    print 'raw: ', raw
    p.close()

    jsonunits = raw.split(os.linesep)
    res = ""

    for unit in jsonunits:
        if not unit:
            continue
        obj = json.loads(unit)
        alternatives = obj['result']

        if len(alternatives) > 0:
            breakflag = False
            for obj in alternatives:
                results = obj['alternative']
                for result in results:
                    res = result['transcript']
                    breakflag = True
                    break
                if breakflag:
                    break
    return res

if __name__ == '__main__':
    import sys
    print stt_google_wav(sys.argv[1])
```

なお、入力としてwaveファイルを必要とする。上記スクリプトを実行すると、以下の出力を得る（例は、「いらっしゃい、どうぞごゆっくり」という発話のwavファイルを入力したもの）。

```
raw:  {"result":[]}
{"result":[{"alternative":[{"transcript":"いらっしゃい どうぞごゆっくり","confidence":0.8348527},{"transcript":"いらっしゃい どうぞゆっくり"},{"transcript":"いらっしゃいどうぞごゆっくり"},{"transcript":"いらっしゃいどうぞ ゆっくり"},{"transcript":"いらっしゃい どうぞ ゆっくり"},{"transcript":"いらっしゃいまどうぞごゆっくり"},{"transcript":"いらっしゃいどうぞゆっくり"},{"transcript":"いらっしゃ い どうぞごゆっくり"},{"transcript":"いらっしゃい ゆっくり"},{"transcript":"らっしゃい どうぞごゆっくり"}],"final":true}],"result_index":0}

いらっしゃい どうぞごゆっくり
```

まず、返ってくるrawファイルは、必ずしも一つのjsonではない。複数のjson文字列が改行で返ってくることを想定する必要がある。従って、行毎にjsonのロードを行い、内容を確認していく。そして、resultキーに値が格納されていた場合にその結果を取り出すという処理を行う。