ReSpeakerというマイクアレイ+Linux搭載デバイスを使って音声認識を試してみました。
できたこと
「Brian, play music!」というと、音楽をかけてくれる
試したこと
Getting Startedに従って以下を試しました。
- ローカル(ネットワークに繋がない)の音声認識で
Hey Siri
的な認識開始ワードを認識する。 - 認識開始ワードに続く言葉を取得し、Bing APIに投げ、結果を取得する。
- 認識結果を使って音楽を再生する。
ReSpeakerとは
SeeedStudioという中国のスタートアップが販売しているデバイスです。
XMOSという会社のマイクロホンアレイ用プロセッサ(複数のマイクを扱い、発話位置の同定や発話部分の音のみを切り出すことができる)と、Ascip7688というWi−Fi内蔵プロセッサモジュールが搭載されています。デフォルトでOpenWRT Linux上にさまざまな便利ライブラリが搭載されています。
ここから購入できるようです。
ReSpeakerの初期設定を行う
ReSpeakerをインターネットに繋げる
ReSpeakerに電源を入れると、ReSpeakerはWi-Fiのアクセスポイントとして立ち上がります。ReSpeakerXXXXのような名前のアクセスポイントに対して接続し、 http://192.168.100.1
に接続すると、家のWi-FiのSSIDとパスワードを入力する画面が表示されます。ここで適切な値を入力すれば、ReSpeakerは家のWi-Fiに接続されます。
あらためてhttp://192.168.100.1
を開くと以下のように接続状態を確認することができます。また、ネットワークやデバイスの各種設定(SSIDの変更、ファームウェアのアップグレード)も行うことができます。
ReSpeakerにSSHで接続する
PCからReSpeakerをアクセスポイントとして接続している状態でSSH接続することができます。
ssh root@192.168.100.1
こんな感じのコンソールになります。デフォルトユーザとパスワードがログインメッセージに書かれてるのがなんかすごい。
Bingの音声認識APIを使う準備をする
Bing Speech APIに無料会員登録を行います。登録が完了するとkey1とkey2が取得できるのですが、今回はkey1のみを使用します。
サンプルを実行する
実行する
-
ReSpeakerチームのが提供するサンプルコードを、ReSpeakerの
/root
以下に置きます。 - 先程取得した音声認識用のKey1を
BING_KEY
としてコード内に記載します。 - 実行します。
python sample.py
サンプルを読む
ローカルの音声認識
ローカルの音声認識はpocketsphinxを使用しています。
ReSpeakerに出荷時に配置されているrespeaker
ライブラリを見てみます。
- 初期化時に音響モデルとキーワードを読み込み(ここで5秒くらい実行時間がかかっています)
def create_decoder():
from pocketsphinx.pocketsphinx import Decoder
path = os.path.dirname(os.path.realpath(__file__))
pocketsphinx_data = os.getenv('POCKETSPHINX_DATA', os.path.join(path, 'pocketsphinx-data'))
hmm = os.getenv('POCKETSPHINX_HMM', os.path.join(pocketsphinx_data, 'hmm'))
dict = os.getenv('POCKETSPHINX_DIC', os.path.join(pocketsphinx_data, 'dictionary.txt'))
kws = os.getenv('POCKETSPHINX_KWS', os.path.join(pocketsphinx_data, 'keywords.txt'))
- 音声データの取得を開始し、
def detect(self, keyword=None):
self.decoder.end_utt()
self.decoder.start_utt()
...
self.status |= self.detecting_mask
self.stream.start_stream()```
- ストリームを認識器に渡し、認識対象となる単語の有無を判定しています。
def detect(self, keyword=None):
...
hypothesis = self.decoder.hyp()
...
if hypothesis.hypstr.find(keyword) >= 0:
result = hypothesis.hypstr
サーバでの音声認識
上記と同じリポジトリにあるbing_speech_api.py
ではAPIを叩いて結果をテキストで取得しています。
def recognize(self, audio_data, language="en-US", show_all=False):
self.authenticate()
if isinstance(audio_data, types.GeneratorType):
def generate(audio):
yield self.get_wav_header()
for a in audio:
yield a
data = generate(audio_data)
else:
data = self.to_wav(audio_data)
params = {
...
}
headers = {
"Authorization": "Bearer {0}".format(self.access_token),
"Content-Type": "audio/wav; samplerate=16000; sourcerate=16000; trustsourcerate=true",
}
url = "https://speech.platform.bing.com/recognize/query"
response = self.session.post(url, params=params, headers=headers, data=data)
if response.status_code != 200:
raise RequestError("http request error with status code {}".format(response.status_code))
result = response.json()
...
サンプルをいじってみる
[トラブルシューティング]Bingサーバにうまく接続できない場合
2017/01/29時点では、pipでインストールされる(または出荷状態でインストールされている)respeakerの音声認識ライブラリが古く、適切にBing APIに接続できない問題がありました。(このコミットがまだ取り込まれていない)
ライブラリのGithubリポジトリからコードを取得し、ReSpeakerにscp
した上でpython setup.py install
することで修正後のコードをインストールすることができました。
トリガーとなる音声を変えてみる
プリインストールされている音響モデルが英語向けのものなので、別の英単語の認識ならすんなりと行きます。
- 1: RespeakerにSSH等で接続します。
- 2:
/usr/lib/python2.7/site-packages/respeaker/pocketsphinx-data/dictionary.txt
- 例:
brian B R AY AH N
- ここの単語から選ぶと良さそう。
- 3:
/usr/lib/python2.7/site-packages/respeaker/pocketsphinx-data/keyword.txt
に認識したい単語とそのthresholdを追記します- 例:
brian /1e-6/
- 例:
- 4: サンプルアプリを再起動すると
Brian!
と呼びかけることでReSpeakerが反応します。
認識中のLEDパターンを変えてみる
linuxが乗っているチップセットとは別のマイコン(arduino/ATmega32U4)に対してSPIでコマンドを送っています。
def write(self, address, data):
data = self.to_bytearray(data)
length = len(data)
if self.hid:
packet = bytearray([address & 0xFF, (address >> 8) & 0xFF, length & 0xFF, (length >> 8) & 0xFF]) + data
self.hid.write(packet)
print(packet)
spi.write(address=address, data=data)
こんな感じにデータをセットします。
pixel_ring.set_color(rgb=0x20FF30)
LEDはWS2812(NeoPixel)を使ってる模様。
感想
- 音声認識のためのライブラリやサンプルコードがすでにインストールされていて、すぐに触り始めることができるので素晴らしいと思いました。
- マイクの基板のみをPCに挿してUSBマイクとしても認識させることができるので、OpenWRTにstickしない形でも遊べそう(未確認)。
- node-pocketsphinxというのがあるらしいので、nodeで書いてみたい。
- 音声をトリガーにして、amazonで注文したり家電をコントロールしたりjokeを返したりしてみたい(g○○gle H○meとかAmaz○n Ech○みたいに)