Amazon Web Services ブログ

Build a Voice Kit with Amazon Lex and a Raspberry Pi

この記事では、広範に利用可能なコンポーネントを利用して、Amazon Lex をどのようにカスタムハードウェアに組み込むかを紹介します。シンプルな音声ベースの AI キットを構築して、Amazon Lex に接続する方法を示します。Raspberry Pi および合計 60 ドル以下の市販のコンポーネントをいくつか使用します。このブログの終わりまでに、Amazon Lex PostContent API に統合された、インターネット接続されたハードウェアデバイスが使用できるようになります。音声制御ロボットおよび音声制御メトロノームなどの、幾つかのボットのデモも行います。

コンポーネント概要

Amazon Lex ハードウェアキットを構築するには、以下のコンポーネントが必要です。

  • Raspberry PI 3 Model BAmazon で 35 ドルから。
  • Kinobo – USB 2.0 ミニマイク、Amazon で 5 ドルから。
  • Adafruit I2S 3W ステレオスピーカーボンネットおよびスピーカー、adafruit で 12 ドルから。
  • (オプション) Qunqi クリアーケースボックスエンクロージャー、Amazon で 20 ドルから。

物理的な作成

Raspberry Pi

図 1. Raspberry PI Model B

このプロジェクトでは、Raspberry PI 3 Model B ストックを使用します。図 1 は、Raspberry Pi をクリアーケースボックスキットに設置したところです。クリアーケースボックスは Pi、デジタルオーディオコントローラー (DAC)、およびスピーカーを置くのにちょうどぴったりですが、必須ではありません。

マイクロフォン

Kinobo USB マイクの取り付けは簡単で、USB ポートを選んで差し込むだけです。

図 2. Raspberry PI 3 Model B と Kinobo USB マイク

図 3. Raspberry PI 3 Model B と Kinobo USB マイク、取り付け後

デジタルオーディオコントローラー

Adafruit I2S 3W ステレオスピーカーボンネットは、3W ステレオアンプのデジタルオーディオコントローラー (DAC) で、Raspberry Pi から直接スピーカーを実行でき、追加の電源を必要としません。ボンネットは、2×20 のヘッダーと 2 つのターミナルブロックと、完全に構築済みのプリント配線回路用基板 (PCB) で構成されます。

図 4. Adafruit I2S 3W ステレオスピーカーボンネット、2×20 ヘッダー、ターミナルブロック

ヘッダーを PCB に接着して Raspberry Pi に接続するため、幾らかの レーザー半田付け が必要になります。

図 5 と 6 は、DAC とヘッダー、ターミナルブロックを半田付けしたところです。半田付けの専門家でない場合は (私たちも違います)、地元の メーカースペース へ行ってみるとよいでしょう。

図 5. Adafruit I2S 3W ステレオスピーカーボンネット (DAC)、下部

図 6. Adafruit I2S 3W ステレオスピーカーボンネット (DAC)、上部

図 7 は、DAC を Raspberry Pi に取り付けたところです。

図 7. DAC を Raspberry Pi に取り付けたところ

講師

DAC を取り付けると、付属のスピーカーを真ん中の圧力端子に接続できます。さらに、スピーカーをクリアーケースボックスの上に取り付けるために、ケースに穴をあけて (Dremel を使用)、それぞれのスピーカーの取り付け穴に対応させました。

図 8. スピーカーを JST ジャックに接続し取り付けたところ

完成製品

図 9 は、完成したキットです。

図 9. Amazon Lex AI Kit を完成させる

インストールとテスト

OS

このプロジェクトには、6 月 21 日の Raspbian Jessie イメージ、2017-06-21-raspbian-jessie.img を使用しました。最新バージョンも使用できます。

  1. RasberryPi.org から、Raspbian Jessie の最新バージョンをダウンロードします。
  2. インストール手順 に沿ってイメージをダウンロードし、SD カードに書き込みます。
ヘッドレスの設定 (オプション)

Raspberry Pi の開発には、ヘッドレス (キーボード、マウス、モニターを必要としない) 設定を使用します。より多くの作業が必要になりますが、Raspberry Pi がネットワークに接続可能な限り、どこからでもアクセスできるようになります。以下のオプション説明は、Raspberry Pi に SSH および VPC アクセスを設定して、ヘッドレスアクセスを有効にする方法を示します。この説明をスキップして、キーボード、マウス、モニターを直接 Raspberry Pi に接続したい場合は、次のセクションに進んでください。

SSH (オプション)

SSH を有効にするには、ssh という名前のファイル (拡張子なし) を SD カードのブートパーティションに置きます。詳細情報については、こちらをご覧ください。

VNC (オプション)

VNC は、グラフィックなデスクトップ共有システムで、(VNC サーバーを実行している) 1 台のコンピュータのデスクトップインターフェースを、(VNC ビューワーを実行している) ほかのコンピュータもしくはモバイルデバイスからリモートコントロールすることができます。Raspberry Pi では、Wi-Fi ネットワークへの接続などのいくつかのタスクは、GUI の使用をすることではるかに簡単になります。

Raspberry Pi VNC ドキュメント に、Raspberry Pi に VNC サーバーおよびビューワーを設定するための、わかりやすい説明が載せられています。

ネットワーク構成

イーサネットケーブルに接続するだけで、Raspberry Pi をネットワークに乗せることができます。GUI (直接または VPC 経由どちらでも) を使用して Raspberry Pi をワイヤレスネットワークに接続するのが一番速い、ということが分かりました。ネットワークへ接続後、Raspberry Pi は raspberry.local または IP アドレスで利用可能になります。

注意: Raspberry Pi の IP アドレスは、Fing で最も簡単に検索できます。

デジタルオーディオコントローラー

I2S DAC のインストールとテストに関しては、Adafruit に詳細な 説明 があります。Adafruit の説明によるインストール手順が便利です。

DAC の使用を最も手早く開始する方法は、1 行インストーラを使用することです。

  1. Raspberry Pi に ssh を実行し、lex という名前の新しいディレクトリを作成します。
    mkdir lex && cd lex/ 
  2. phatdac インストールスクリプトを実行します。
    curl https://get.pimoroni.com/phatdac | bash
  3. 次の処理に進むことを求めるプロンプトが表示されたら、[y] を入力します。
  4. 再起動を求めるプロンプトが表示されたら、[y] を入力します。再起動が必要な場合、Raspberry Pi に再接続した後でスクリプトを再実行します。
  5. 「今システムをテストしますか」と聞かれたら、[y] を入力します。

それぞれのステレオチャンネルの音声サンプルが流れます。手動インストールオプションを含む、DAC 使用に関する詳細な説明は、ここから見ることができます。

マイク

マイクロフォン使用のために何かをインストールする必要はありません。必要なのは、ALSA ライブラリがインストールされていることだけです。次のコマンドを使用して、マイクロフォンが動作しているかどうかをテストできます。

sudo arecord -D plughw:1 -r 32000 -f S16_LE temp.wav 

話し終えたら、スクリプトを終了させるために [ctrl-C] を押します。次のコマンドを使用して録音した音声をテストできます。

sudo aplay ./temp.wav

temp.wav を再生して録音した音声が流れたら、Amazon Lex に音声をキャプチャおよびストリーミングする準備ができたことになります。

Amazon Lex との統合

Node.js をインストールします。

apt-get を使用して Node と npm をインストールします。Raspberry Pi のターミナルウィンドウに以下を入力します。

sudo apt-get install -y nodejs npm

インストールされたバージョンを確認し、Node と npm がインストールされたことを確認します。

npm -v && node -v

注意: ノードパッケージと名前が競合する場合、nodejs としてインストールされます。/usr/bin/node に手動でシンボリックリンクを作成するか、次のコマンドでノードの代わりに nodejs を使用することができます。

SDK のインストール

AWS SDK for Node.js のインストールに推奨される方法は、npm を使用することです。ターミナルウィンドウで次のように入力します。

npm install aws-sdk

ボット会話ランチャースクリプト

マイクロフォンとスピーカーが動作するようになり、Amazon Lex JavaScript SDK をインストールしたので、PostContent オペレーションを呼び出してボットと会話できるようになりました。

このノードスクリプトは音声入力を聞き、音を検出して、Amazon Lex への音声のストリーミングを開始します。無音が検出されるとストリーミングを終了し、レスポンスを再生します。スクリプトはリッスンしつづけ、会話の状態が Fulfilled になるまで応答し続けます。

// lex.js 
var AWS = require('aws-sdk'),
   fs = require('fs'),
   ts = require('tailstream'),
   exec = require('child_process').exec;

   var FULFILLED = 'Fulfilled',
   RESPONSE_FILE = 'response.mpeg',
   REMOVE_REQUEST_FILE = 'rm request.wav',
   SOX_COMMAND = 'sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer --endian little - silence 1 0 1% 5 0.3t 2% > request.wav',
   streaming = false,
   inputStream,
   lexruntime = new AWS.LexRuntime({
     region: 'us-east-1',
     credentials: new AWS.Credentials(
       <KeyId>,
       <SecretKeyId>, null)
   });   

var setupStream = function() {
   streaming = true;
   inputStream = ts.createReadStream('./request.wav');
   var params = {
     botAlias: '$LATEST',
     botName: <BotName>,
     userId: 'lexHeadTesting',
     contentType: 'audio/l16; rate=16000; channels=1',
     inputStream: inputStream
   };

   lexruntime.postContent(params, function(err, data) {
     if (err) {
       console.log(err, err.stack);
       process.exit(1);
     } else {
       fs.writeFile(RESPONSE_FILE, data.audioStream, function(err) {
         if (err) {
           return console.log(err);
           process.exit(1);
         }
       });
       var playback = exec('sudo mpg321 ' + RESPONSE_FILE);
       playback.on('close', function(code) {
         exec('rm ' + RESPONSE_FILE);
         if (data.dialogState !== FULFILLED) {
           streaming = false;
           record();
         }
       });
     }
   });
 }

var record = function() {
   var recording = exec(SOX_COMMAND);
   recording.stderr.on('data', function(data) {
     console.log(data);
     if (!streaming) {
       setupStream();
     }
   });
   recording.on('close', function(code) {
     inputStream.done();
     exec(REMOVE_REQUEST_FILE);
   });
 }
record();

スクリプトを実行する前に、いくつかの依存関係をインストールする必要があります。スクリプトは、録音と再生を fstailstream、および child_process npm パッケージと SoXmpg321 コマンドに依存しています。

npm パッケージ

~/lex ディレクトリから、以下のコマンドを使用して npm の依存関係をインストールします。

npm install fs tailstream child_process 
SoX

SoX は、最も人気のあるフォーマットで音声ファイルの読み取りと書き込みを行い、効果音を設定することができます。複数の入力ソースを組み合わせたり、音声を合成したりすることができ、多くのシステム上で汎用音声プレーヤーまたはマルチトラック音声レコーダーとして動作します。SoX を使用して音声のキャプチャを開始、停止したり、キャプチャした音声をトリミング (最初と最後の無音を削除) します。次のコマンドを使用して SoX をインストールします。

sudo apt-get install sox 

以下は、Amazon Lex が認識できるフォーマットを使用して音声を録音するため、またさらに重要なこととして、無音の検出とトリミングを行うために使用される SoX のコマンドです。このコマンドは、参考までに記載します。必ずしも実行する必要はありません。

sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer –endian little – silence 1 0 1% 4 0.3t 2%

コマンドの最初の部分は、WAV ファイルとして 16000 Hz でサンプリングを行い、PCM– エンコード (16 ビットのリトルエンディアン署名) された音声を録音したいという意味です。

sox -d -t wavpcm -c 1 -b 16 -r 16000 -e signed-integer --endian little

2 番目の部分は、録音の前後に無音が検出された場合の処理方法を指定します。

silence 1 0 1% 4 0.3t 2% 

最初の 3 つの値は、最初に無音があれば、1% 以上の音を 0 秒まで削除します。% はしきい値で、どのサンプル値を無音として扱うか指定するときに使用されます。2 つ目の 3 つの値は、少なくとも 2% 以下の 0.3 秒の無音が 4 回あった場合に録音を停止します。

mpg321

Amazon Lex からレスポンスを受け取ることに成功したら、mpg321 を使用して音声ストリームを再生します。mpg321 はとても一般的なコマンドライン mp3 プレーヤーです。次のコマンドを使用して mpg321 をインストールします。

sudo apt-get install mpg321 

テスト

依存関係をインストールしたので、Amazon Lex 会話スクリプトをテストできるようになりました。~/lex ディレクトリから、上記のスクリプトのコンテンツとともに lex.js というファイルを作成します。

注意: 認証情報 および ボット名 を使用して、サンプルスクリプトを確実に更新してください。

終わったら、スクリプトを保存し、次のコマンドを使用して実行します。

node lex.js 

すべてが正しければ、ターミナルに SoX コマンドからの出力が表示されます。ボットに向かってはっきりと発話し、Amazon Lex のレスポンスをリッスンします。スクリプトは、会話の状態が Fulfilled になるまで継続して実行されます。ボットがない場合の構築方法については、「Amazon Lex ドキュメント」をご覧ください。インスピレーションのために、「それで何ができますか?」をチェックしてください。このセクションには、異なるボット統合についてのビデオがあります。

ホットワード

この時点で、機能する音声キャプチャと再生、Amazon Lex PostContent オペレーションベースのダイアログを編成するノードスクリプトが用意できました。プロジェクトを完成させるため、ホットワードを発話してキットを呼び出せるよう、ホットワード検出を追加します。このプロジェクトでは、ホットワード検出にサードパーティーライブラリ (Snowboy) を使用します。Snowboy はカスタマイズ可能な、ローカルで動作する “ホットワード” 検出エンジンで、Raspberry Pi に直接使用できる互換性を持っています。

インストール

以下の手順、もしくは 詳細な Snowboy クイックスタート手順 に従ってください。

~/lex ディレクトリに「snowboy」という新しいディレクトリを作成し、Snowboy バイナリをダウンロードします。

mkdir snowboy && cd ~/lex/snowboy && wget https://s3-us-west-2.amazonaws.com/snowboy/snowboy-releases/rpi-arm-raspbian-8.0-1.2.0.tar.bz2 

Snowboy tar ファイル を解凍します。

tar -xvf ./rpi-arm-raspbian-8.0-1.2.0.tar.bz2 cd rpi-arm-raspbian-8.0-1.2.0 

Snowboy の依存関係をインストールします。

sudo apt-get install python-pyaudio python3-pyaudio sox 

pyaudio をインストールします。

pip install pyaudio 

libatlas-base-dev もインストールする必要があります。(このステップは Snowboy の手順とは異なります。)

sudo apt-get install libatlas-base-dev 

テスト

インストールが完了したら、Snowboy のテストスクリプトを実行できます。以下のディレクトリにいることを確認してください。~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0.

python demo.py resources/snowboy.umdl 

スクリプトがリッスン中であるとレポートしたら、ホットワードの「Snowboy」をはっきり発音してください。ホットワードが認識されたことを示すビープ音が聞こえます。

カスタムホットワード (オプション) を作成します。

次のセクションでは、Snowboy デモスクリプトを変更して lex.js ボット呼び出し元を実行します。カスタムホットワードを使用したい場合、個人用ホットワードモデルを Snowboy dashboard から構築してダウンロードできます。このデモでは、「botbot」と「metronome」用の「ホットワード」モデルを作成しました。

すべて一緒に試してみる

これで、ホットワードループを設定する準備ができました。以下のコードは、Snowboy バイナリに含まれている demo.py ファイルにわずかな変更を加えたものです。開始するとホットワードをリッスンし、ホットワードを聞き取るとホットワード検出を停止して Lex ボット呼び出し元スクリプトを実行し、ボット呼び出し元スクリプトが完了した後で再起動します。

import snowboydecoder 
import os 
import sys 
import signal 
import subprocess
   
interrupted = False
   
def signal_handler(signal, frame):
     global interrupted
     interrupted = True
     
def interrupt_callback():
     global interrupted
     return interrupted
   
def on_hot_word():
 	detector.terminate()
 	pro = subprocess.Popen(["node", "../../lex.js"]).wait()
 	print("Restarting...")
 	os.execv(sys.executable, ['python'] + sys.argv)
   
if len(sys.argv) == 1:
     print("Error: need to specify model name")
     print("Usage: python demo.py your.model")
     sys.exit(-1)
   
model = sys.argv[1]
   
# capture SIGINT signal, e.g., Ctrl+C signal.signal(signal.SIGINT, signal_handler)
   
detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')
   
# main loop 
detector.start(detected_callback=on_hot_word,
                interrupt_check=interrupt_callback,
                sleep_time=0.03)
   
detector.terminate()

~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0 ディレクトリに lex-wake.py という新しいファイルを作成し、上記のコードをコピーして保存します。次のコマンドを使用してテストできます。

python lex-wake.py Botbot.pmdl 

注意: ここでの個人用ホットワードモデルは “Botbot.pmdl” ですが、自分で作成したもの、または Snowboy モデルに含まれる「resources/snowboy.umdl」を使用することもできます。

ホットワードループの開始が表示されます。ホットワードをはっきり発音します。ボットが呼び出され、会話の状態が「Fulfilled」になると、ホットワードループは再びリッスンを開始します。

これで、自分の AI キットが作成できました。「それで何ができますか?」をチェックしてください。以下のセクションでは、音声制御ロボット、話す呼び鈴、メトロノームその他、新しいキットのわくわくするような使用方法の例が取り上げられています。

起動時に実行 (オプション)

起動時にホットワードをリッスンするには、/etc/rc.local ファイルを編集してホットワードスクリプトを含めてください。

python ~/lex/snowboy/rpi-arm-raspbian-8.0-1.2.0/lex-wake.py Botbot.pmdl & 

参照

参照コードを完成させる

https://github.com/awslabs/aws-lex-ai-kit

それで何ができますか?

任意の Amazon Lex ボットに接続できます。何を構築したかについて、ご意見やご感想をお寄せください。音声制御 GoPiGo ロボットおよび音声制御メトロノームを作成するため、2 つのボットにボイスキットを接続しました。

音声制御ロボット

この例では、Drive と Turn の 2 つのインテントがあり、方向、距離、単位用のスロットを持っています。フルフィルメントは Lambda function で処理され、IoT デバイスシャドウが更新されて、ロボットが動きます。

音声制御メトロノーム

この例では、インテントパラメータを直接ボイスキットに返します。インテントには、Tempo という 1 つのスロットしかありません。テンポ値が返されると、メトロノームは要求されたテンポで始まり、オンボードのスピーカーを使用して拍子を刻みます。

投稿についてのご意見やご感想、ご質問、お客様の組み立てたボイスキット音声プロジェクトについてのお便りなどをお待ちしております。以下のコメントセクションからフィードバックをお寄せください。


その他の参考資料

ブラウザで音声入力をキャプチャして Amazon Lex へ送る 方法を学びましょう。


今回のブログの投稿者について

Andrew Lafranchise は、AWS Deep Learning のシニアソフトウェア開発エンジニアです。 Lex 開発者エクスペリエンスを向上させるため、さまざまなテクノロジーに取り組んでいます。時間があるときは家族との時間を楽しみ、3 才の娘とやり取りできる Lex ボットを開発中です。