以前、以下の記事に書きましたが、Raspberry Pi Zero Wは”OK Google”などの「ウェイクワード(Wake Word)」に対応していません。
そこで下記のようにpushtotalkを使ってGoogle Assistantを使ってみましたが、やはりウェイクワードが使えないのは辛い。。
このため、Juliusでウェイクワードを拾い、Google Assistant の pushtotalk に通知することを考えましたが、Juliusの認識が遅すぎる&Juliusと Google Assistant で音声デバイスを取り合う(?)ため諦めました。
なんとかならないかとネットを彷徨ったところ、以下のサイトを見つけました。
AlexaとGoogle Assistantの同時待ち受けを可能にする方法を公開されているページですが、この中に pushtotalk をウェイクワードで起動する方法が記載されています。
Snowboyというアプリでウェイクワードを認識し、pushtotalkを起こしているようです。
https://qiita.com/Dimeiza/items/1a77191a5febd57e98c4
早速参考にさせていただき、Snowboyを組み込んでみました。
Snowboyを導入する
ダウンロード
以下のページに「Raspberry Pi with Raspbian 8.0, all versions (1/2/3/Zero)」という行があり、"1/2/3/Zero"の部分をクリックするとダウンロードできます。
Snowboy, a Customizable Hotword Detection Engine — Snowboy 1.0.0 documentation
展開
ダウンロードしたファイルをWinSCPなどでRaspberry Pi Zero Wに持っていき、下記のコマンドで展開します。ダウンロードしたファイルは /home/pi/tmp に置いたとします。
cd /home/pi/tmp
bunzip2 rpi-arm-raspbian-8.0-1.1.1.tar.bz2
tar xvf rpi-arm-raspbian-8.0-1.1.1.tar
必須パッケージの適用
Snowboyを使用する上で必要になるパッケージをインストールします。
sudo apt-get install python-pyaudio python3-pyaudio sox
sudo apt-get install libatlas-base-dev
sudo apt-get install swig
pip install pyaudio
Snowboyの共有ライブラリをPython3用に置換
初めから入っているSnowboyの共有ライブラリ(_snowboydetect.so)はPython3には対応していないようだったので、以下の方法でPython3用を作成し、元のファイルと置換しました。
cd /home/pi/tmp
git clone https://github.com/Kitt-AI/snowboy.git
cd /home/pi/tmp/snowboy/swig/Python3
make clean
make
cp _snowboydetect.so /home/pi/tmp/rpi-arm-raspbian-8.0-1.1.1
Snowboyを動かしてみる
以下のコマンドを実行すると、画面になにやら色々出てきて「Listening... Press Ctrl+C to exit」で止まります。
python demo.py rources/snowboy.umdl
そこですかさず「Snowboy」と声をかけると、チン!という音がして「INFO:snowboy:Keyword 1 detected at time: 2019-xx-xx xx:xx:xx」と表示されました。
うまく認識できたようです。
SnowboyからGoogle Assistantにイベントを通知する
Snowboyでウェイクワード認識ができましたので、認識したことを pudhtotalk に通知する方法を考えます。
pushtotalk はキー入力を待ちますので、まずこの部分をSnowboyからイベント待ちするように書き換えます。今回は手っ取り早くソケットを使ってイベントを送るようにしました。
pushtotalk.pyというソースコードの「click.pause(info='Press Enter to send a new request...')」の部分でキー入力を待っていますので、以下のように書き換えました。
赤字が変更箇所です。
wait_for_user_trigger = not once
wait_init()
while True:
if wait_for_user_trigger:
#click.pause(info='Press Enter to send a new request...')
wait_snowboy()
continue_conversation = assistant.assist()
# wait for user trigger if there is no follow-up turn in
# the conversation.
wait_for_user_trigger = not continue_conversation# If we only want one conversation, break.
if once and (not continue_conversation):
break
wait_close()
wait_init、wait_snowboy、wait_closeは下記のようにしました。
def wait_init():
global sock
host = '127.0.0.1'
port = 36363sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))def wait_close():
global sock
sock.close()def wait_snowboy():
global sock
backlog = 10
bufsize = 1024
sock.listen(backlog)
conn, address = sock.accept()
while True:
msg = conn.recv(bufsize)
if not msg:
continue
else:
conn.send(msg)
break
conn.close()
return
以下のimportも pushtotalk.py に追記します。
import socket
次にSnowboyのソースコード(snowboydecoder.py)を書き換えます。
play_audio_fileというメソッドでウェイクワード認識後の処理を行っているので、ここに下記のイベント送信処理を入れ込みます。チン!という音を出した後に送信するようにしました。
host = '127.0.0.1'
port = 36363
backlog = 10
bufsize = 1024
smsg = b"SNOWBOY"sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
sock.send(smsg)
rmsg = sock.recv(bufsize)
sock.close()
以上でできるようになりました!と言いたいところでしたが、問題発生。。
pushtotalkを起動してからSnowboyを起動すると「PortAudioError」というエラーが。。
Webを検索すると以下のページを見つけたため、pulseaudioをインストールして設定したところ解決しました。助かった~。
願いごとを叶えてくれる「かみさま」をRaspberry Piに実装する - 現ア集のブログ
なお、私のRaspberry Pi Zero WはUSB接続のサウンドカードを使っているのですが、オンボードサウンド(bcm2835)が有効になっているとpulseaudioがうまく動かなかったので /boot/config.txt を下記のように編集して再起動しました。
dtparam=audio=off
ちなみにこのページにはSnowboyのウェイクワードを自分の好きなものに変える方法も記載されています。いずれに参考にさせていただこうと思っています。