Raspberry Pi 2でAmazon Echoを作る

  • 59
    いいね
  • 1
    コメント

AmazonからAlexa Voice Service(AVS)の使い方についてのサンプルが公開されていたので、試してみました。
https://github.com/amzn/alexa-avs-raspberry-pi

サンプル動画

出来上がりはこんな感じで、Alexaが質問に反応して、答えてくれるようになります。
Raspberry Pi2 and Alexa Voice Service

いきなり感想

Raspberry Pi用のサンプルでは、GUIでクライアントを起動する必要があり、音声の認識には事前にボタンを押してといった操作が必要なので、Amazon Echoみたいに好きなタイミングで話しかけて、反応するといったことが出来ませんでした。
Amazon Echoのようにトリガーキーワードである Alexa を言わなくても反応するのは、ボタンで音声認識を開始させているからだと思います。

音声だけで反応させるには、常時オーディオを監視して、特定のキーワードが見つかったら、それ以降の音声を認識させるといった作りこみを、クライアントアプリで出来るようにすれば、よりAmazon Echoの様なデバイスが作れるのではないでしょうか。

Amazon Fire Stickのリモコンも、Alexaを使う時はボタンを押してる間だけ音声認識させるので、実装するデバイスの用途次第で、トリガーをどうするか決めれば良さそうです。

サンプルを元に進めます

https://github.com/amzn/alexa-avs-raspberry-pi

準備するもの

  • Raspberry Pi 2
  • マイク
  • スピーカー(私の例では、HDMIでTVに繋いだので、音声はTVから出力されます)

Raspberry PiのOS

$ uname -a
Linux raspberrypi 4.1.17-v7+ #838 SMP Tue Feb 9 13:15:09 GMT 2016 armv7l GNU/Linux

VNCサーバの設定

AVSのサンプルを動かす際にはGUIが必要となりますので、別途モニターを用意しない場合は、元の手順のようにVNCサーバのセットアップをしてリモートデスクトップを使ってサンプルを動かす必要があります

VLCをセットアップ

sudo apt-get update
sudo apt-get install vlc-nox vlc-data

VLCの場所を確認

$ whereis vlc
vlc: /usr/bin/vlc /usr/lib/vlc /usr/share/vlc /usr/share/man/man1/vlc.1.gz

環境変数の設定

export LD_LIBRARY_PATH=/usr/lib/vlc
export VLC_PLUGIN_PATH=/usr/lib/vlc/plugins

nodejsのインストール

curl -sL https://deb.nodesource.com/setup | sudo bash -
sudo apt-get install nodejs

$ node -v
v0.10.43

JDKのインストール

こちらからJDKをダウンロードします。
今回ダウンロードしたのは、Linux ARM 32 Soft Float ABI(jdk-8u77-linux-arm32-vfp-hflt.tar.gz 新しいバージョンを使う場合は適宜ファイル名を置き換えて進めてください)
注:2016/6/5) リンク先からLinux ARM 32 Soft Float ABIがない場合がありますが、Oracleが数週間毎にSoft/Hardと名称を変えるので、最新のLinux ARM 32 Hard Float ABI or Linux ARM 32 Hard Float ABIをダウンロードして使ってください。 (@jhotta さんありがとうございます)

sudo tar zxvf jdk-8u77-linux-arm32-vfp-hflt.tar.gz -C /opt

sudo update-alternatives --install /usr/bin/javac javac /opt/jdk1.8.0_77/bin/javac 1
sudo update-alternatives --install /usr/bin/java java /opt/jdk1.8.0_77/bin/java 1

インストールしたものを使うように設定

sudo update-alternatives --config javac
sudo update-alternatives --config java

確認

$ java -version

java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) Client VM (build 25.77-b03, mixed mode)

$ javac -version

javac 1.8.0_77

Mavenのインストール

こちら ダウンロードしてくる

sudo tar zxvf apache-maven-3.3.9-bin.tar.gz -C /opt

export M2_HOME=/opt/apache-maven-3.3.9
export PATH=$PATH:$M2_HOME/bin

確認

mvn -version

Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T01:41:47+09:00)
Maven home: /opt/apache-maven-3.3.9
Java version: 1.8.0_77, vendor: Oracle Corporation
Java home: /opt/jdk1.8.0_77/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "4.1.17-v7+", arch: "arm", family: "unix"

Alexa Voice Serviceの準備

手順ページ(3 - Getting started with Alexa Voice Service)に書かれている通りにデバイスを追加します
https://github.com/amzn/alexa-avs-raspberry-pi#3---getting-started-with-alexa-voice-service

サンプルをRaspberry上にダウンロード

wget https://github.com/amzn/alexa-avs-raspberry-pi/archive/master.zip

unzip master.zip
sudo mv alexa-avs-raspberry-pi-master /opt/alexa-avs-raspberry-pi

自己証明書の準備

sudo apt-get install openssl

cd /opt/alexa-avs-raspberry-pi/samples/javaclient

ssl.cnfを編集して証明書の情報を入力します
countryName は2文字じゃないと証明書の生成に失敗します。
commonNameは、/opt/alexa-avs-raspberry-pi/samples/companionService/config.js のcompanionService.serviceUrlと一致させておく必要があります。(デフォルトからいじらなければOK)

[req]
distinguished_name      = req_distinguished_name
prompt                  = no

[v3_req]
subjectAltName          = @alt_names

[alt_names]
DNS.1                   = localhost
IP.1                    = 127.0.0.1
IP.2                    = 10.0.2.2

[req_distinguished_name]
commonName              = $ENV::COMMON_NAME
countryName             = JP
stateOrProvinceName     = Tokyo
localityName            = tokyo
organizationName        = sparkgene
organizationalUnitName  = dev

証明書生成スクリプトに実行権限を付けて実行する

chmod +x generate.sh

./generate.sh

Product ID: pi2_alexa
Serial Number: 123456
Password for Keystores (won't echo): Generating RSA private key, 4096 bit long modulus
.................................................................................................................................++
...............................................................................................................................................................................++
e is 65537 (0x10001)
Generating RSA private key, 2048 bit long modulus
.+++
...................................+++
e is 65537 (0x10001)
Signature ok
subject=/CN=sparkgene/C=JP/ST=Tokyo/L=tokyo/O=SPARKGENE/OU=development
Getting CA Private Key
Generating RSA private key, 2048 bit long modulus
...............................+++
...............................................................................................................................................+++
e is 65537 (0x10001)
Signature ok
subject=/CN=sparkgene/C=JP/ST=Tokyo/L=tokyo/O=SPARKGENE/OU=development
Getting CA Private Key
Generating RSA private key, 2048 bit long modulus
..................+++
................................................+++
e is 65537 (0x10001)
Signature ok
subject=/CN=sparkgene/C=JP/ST=Tokyo/L=tokyo/O=SPARKGENE/OU=development
Getting CA Private Key

nodejsの設定ファイルに生成した証明書のパスを指定する。

sslKey: '/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/server/node.key',
sslCert: '/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/server/node.crt',
sslCaCert: '/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/ca/ca.crt',

javaクライアントの設定ファイルに生成した証明書のパスを指定する。
パスワード指定していないので、Passphraseは空にしてます。

{
    "productId":"",
    "dsn":"",
    "provisioningMethod":"",
    "companionApp":{
        "localPort":8443,
        "sslKeyStore":"/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/server/jetty.pkcs12",
        "sslKeyStorePassphrase":"",
        "lwaUrl":"https://api.amazon.com"
    },
    "companionService":{
        "serviceUrl":"https://localhost:3000",
        "sslClientKeyStore":"/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/client/client.pkcs12",
        "sslClientKeyStorePassphrase":"",
        "sslCaCert":"/opt/alexa-avs-raspberry-pi/samples/javaclient/certs/ca/ca.crt"
    }
}

Raspberry Piをデバイス登録するためのアプリを準備

cd /opt/alexa-avs-raspberry-pi/samples/companionService

npm install

Security Profileを有効にする

https://github.com/amzn/alexa-avs-raspberry-pi#6---enable-security-profile
を参考に、有効にします。

各種configファイルに設定する

/opt/alexa-avs-raspberry-pi/samples/companionService/config.jsを編集して、clientId、clientSecret、productsを設定します。
元のサンプル通りの命名で進めるとproductsは products: {"my_device": ["123456"]} と指定します。

/opt/alexa-avs-raspberry-pi/samples/javaclient/config.jsonを編集して、productId、dsn、provisioningMethodを設定します。

/opt/alexa-avs-raspberry-pi/samples/javaclient/pom.xmlのdependenciesに以下を追加する

<dependency>
  <groupId>net.java.dev.jna</groupId>
  <artifactId>jna</artifactId>
  <version>4.1.0</version>
  <scope>compile</scope>
</dependency>

Companion Serviceサーバを実行する

cd /opt/alexa-avs-raspberry-pi/samples/companionService/
npm start

# サーバが実行され、ポート3000でリッスンを開始します

> alexa-voice-service-sample-companion-service@1.0.0 start /opt/alexa-avs-raspberry-pi/samples/companionService
> node ./bin/www

This node service needs to be running to store token information memory and vend them for the AVS app.

Listening on port 3000

クライアントを起動

別のターミナルウィンドウを起動してクライアントを実行します

cd /opt/alexa-avs-raspberry-pi/samples/javaclient/
chmod +x install-java8.sh
./install-java8.sh

mvn validate
mvn install

mvn exec:exec

アクティベーションする

クライアントが起動すると、デバイスを登録するためのURLが表示されるので、それをブラウザに貼り付けて、有効にします。

IMG_7187.JPG

アクティベーションがされると、クライアントの画面でStart Listening をクリックして音声認識させます。