myalexa.jpeg

ポストスマホの有力候補といえばスマートスピーカーということで、とりあえずデバイス側を作ってみました。
今回は米国で既に先行しているamazon Alexaとやり取りしたいと思います。
なんか色々アレクサと対話したいので英語、米語、ドイツ語、日本語と切り替えれるようにしました。

用意するもの

  • プロト基盤:Raspberry Pi3(2でも良いがwifiが付いているので3)
  • スピーカー:USB,3.5mmでもいいしHDMIでもいい
  • mircoSD:RSPIとの依存があるのでこの中から選ぶことを強くおすすめします。
  • USBキーボード:ラズパイ操作用
  • USBマウス:ラズパイ操作用
  • HDMIケーブル:モニターにつなぐため
  • HDMIモニタ:ラズパイ操作用
  • macbook:OSダウンロード用

大まかな流れ

ラズパイの設定
1. OSインストール
2. OSセットアップ
AVSの構築
1. SDKインストールと環境設定
2. SDKのビルド
3. AVSの認証
4. 実行

はい、では行ってみよう。

ラズパイの設定

1. OSインストール
まずはOS(raspbian)をインストールしましょう。
1. 1 OSのダウンロード
このサイトからダウンロード(https://www.raspberrypi.org/downloads/)

今回はraspbianというDebianベースのOSを使います。
ここにはNoobsという初心者用のインストーラーもあるけど、イケてる君は
Bootイメージを直接扱った方が時短になるので迷わずRasbian stretch2017-09-07を選ぼう。
※国内外の文献ではAVSのSDKがstretchに対応していないと書いているけど、そこはクリアしているので大丈夫。

1.2 SDカードのフォーマット

  • macbookにmicroSDカードを差す。
  • マウントが出来たらSDカードのフォーマットを行う。
  • SDカードの場所を確認
    $diskutil list
    これでSDカードのディレクトリが分かります。(ex:/dev/disk2)

  • SDカードのフォーマット(FATね)
    $sudo diskutil eraseDisk FAT32 RASBIAN MBRFormat /dev/disk2

    SDカードのサイズが30GB以下はFAT32とし、それ以上のサイズはexFATする。
    RASBIANは任意で好きな名前を付けてね

  • SDカードをアンマウントし、コピーができる状態が完了
    $sudo diskuitl unmount /dev/disk2
    disk2をアンマウントする

1.3 SDカードのコピー

  • ダウンロードしたOSを解凍
    $tar xzf 2017-09-07-raspbian-stretch.zip

  • 解凍したイメージをSDカードにコピー
    $sudo dd bs=1m if=2017-09-07-raspbian-stretch.img of=/deb/rdsik2

    なぜデバイス名rdiskになってるの?とお気づきですか。
    それはrdiskの方が書き込む速度が早いからです。
    disk2もrdisk2も同じ場所ですが、disk2とした場合、ランダムアクセスが可能となるデバイスとして転送データがUserSpaceという4KBのバッファを経由して処理されます。
    これはマルチタスクがゆえのことなのですが、これをrdiskで指定することにより、バッファを経由せずにダイレクトでシーケンシャルに処理が進むためにdiskよりも高速になります。
    興味と時間のある方はdisk指定で4GBのコピーの旅をお楽しみ下さい。

2 OSセットアップ
いよいよラズパイを動かしましょう。

2.1 OSの起動
RSPI3にモニタ、キーボード、マウス、SDカードを入れて電源ON
rasbian.jpeg

2.2 初期セットアップ

  • ターミナルを起動し次の設定を行う sudo raspi-configでもいいしGUIでもOK。とにかくこれを設定 ・タイムゾーンの設定 ・wifiの設定 ・SSHの設定 ・キーボード設定 ※お好みに合わせてVNCも設定

AVSの構築

ここから本番。
1. SDKインストールと環境設定
1.1 まずは最低限必要なパッケージの更新とインストール

  • パッケージの更新
    sudo apt-get update

  • で、必要なパッケージをインストール

sudo apt-get -y install git gcc cmake build-essential libsqlite3-dev libcurl4-openssl-dev libfaad-dev libsoup2.4-dev libgcrypt20-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-good libasound2-dev doxygen

1.2 開発環境のディレクトリを作成

cd /home/pi/ && mkdir sdk-folder && cd sdk-folder && mkdir sdk-build sdk-source third-party application-necessities && cd application-necessities && mkdir sound-files

1.3 フリーの音声ライブラリ(portaudio)を拝借
ディレクトリ移動&ダウンロード&解凍&configure&makeを一気に行います

cd /home/pi/sdk-folder/third-party && wget -c http://www.portaudio.com/archives/pa_stable_v190600_20161030.tgz && tar zxf pa_stable_v190600_20161030.tgz && cd portaudio && ./configure --without-jack && make

1.4 commentjsonのインストール
AVS認証時に必要になるAlexaClientSDKConfig.jsonに書き込みを行うために必要
pip install commentjson

1.5 タイマーとアラーム音をアマゾンのサイトからダウンロード

cd /home/pi/sdk-folder/application-necessities/sound-files/ && wget -c https://images-na.ssl-images-amazon.com/images/G/01/mobile-apps/dex/alexa/alexa-voice-service/docs/audio/states/med_system_alerts_melodic_02._TTH_.mp3 && wget -c https://images-na.ssl-images-amazon.com/images/G/01/mobile-apps/dex/alexa/alexa-voice-service/docs/audio/states/med_system_alerts_melodic_02_short._TTH_.wav && wget -c https://images-na.ssl-images-amazon.com/images/G/01/mobile-apps/dex/alexa/alexa-voice-service/docs/audio/states/med_system_alerts_melodic_01._TTH_.mp3 && wget -c https://images-na.ssl-images-amazon.com/images/G/01/mobile-apps/dex/alexa/alexa-voice-service/docs/audio/states/med_system_alerts_melodic_01_short._TTH_.wav

2. SDKのビルド
2.1 AVSのSDKをクローンします

cd /home/pi/sdk-folder/sdk-source && git clone git://github.com/alexa/avs-device-sdk.git

2.2 ウェイクワードのエンジン(Sensory)もクローン
これをすると「アレクサ!」で反応してくれるようになります。

cd /home/pi/sdk-folder/third-party && git clone git://github.com/Sensory/alexa-rpi.git

で、それの利用規約に同意します。

cd /home/pi/sdk-folder/third-party/alexa-rpi/bin/ && ./license.sh 

2.3 日本語化対応
デフォルトは英語なので、これらのソースを変更し日本語に対応させます。

まずはエンドポイントを日本に変更

/sdk-folder/sdk-source/avs-device-sdk/SampleApp/src/SampleApplication.cpp
//68行目
// Default AVS endpoint to connect to.
static const std::string DEFAULT_ENDPOINT("https://avs-alexa-fe.amazon.com");

アプリ実行中のメニューに日本語切り替えを追加

/sdk-folder/sdk-source/avs-device-sdk/SampleApp/src/UIManager.cpp
//89行目のこのメニューに日本語を追加し、英語と入れ替える
static const std::string LOCALE_MESSAGE =
    "+----------------------------------------------------------------------------+\n"
    "|                          Language Options:                                 |\n"
    "|                                                                            |\n"
    "| Press '1' followed by Enter to change the language to US English.          |\n"
    "| Press '2' followed by Enter to change the language to UK English.          |\n"
    "| Press '3' followed by Enter to change the language to German.              |\n"
   "+----------------------------------------------------------------------------+\n";
//を、次の内容に変更する
static const std::string LOCALE_MESSAGE =
    "+----------------------------------------------------------------------------+\n"
    "|                          Language Options:                                 |\n"
    "|                                                                            |\n"
    "| Press '1' followed by Enter to change the language to Japan.               |\n"
    "| Press '2' followed by Enter to change the language to UK English.          |\n"
    "| Press '3' followed by Enter to change the language to German.              |\n"
    "| Press '4' followed by Enter to change the language to US English.          |\n"
    "+----------------------------------------------------------------------------+\n";

メニューの変更をテーブルにも反映

/sdk-folder/sdk-source/avs-device-sdk/SampleApp/src/UIManager.cpp
//44行目 日本語を追加し、英語と入れ替える
static const std::unordered_map<char, std::string> LOCALE_VALUES({{'1', "ja-JP"}, {'2', "en-GB"}, {'3', "de-DE"},{'4', "en-US"}});

2.4 AVSのSDKをビルド
まずはcmakeを走らせます。
ウェイクワードをONやgstreamer許可なのをオプションとして設定しています。

cd /home/pi/sdk-folder/sdk-build && cmake /home/pi/sdk-folder/sdk-source/avs-device-sdk -DSENSORY_KEY_WORD_DETECTOR=ON -DSENSORY_KEY_WORD_DETECTOR_LIB_PATH=/home/pi/sdk-folder/third-party/alexa-rpi/lib/libsnsr.a -DSENSORY_KEY_WORD_DETECTOR_INCLUDE_DIR=/home/pi/sdk-folder/third-party/alexa-rpi/include -DGSTREAMER_MEDIA_PLAYER=ON -DPORTAUDIO=ON -DPORTAUDIO_LIB_PATH=/home/pi/sdk-folder/third-party/portaudio/lib/.libs/libportaudio.a -DPORTAUDIO_INCLUDE_DIR=/home/pi/sdk-folder/third-party/portaudio/include

そしてmake
make SampleApp -j3

makeのjオプションは並行処理の数で多い方がより高速になるがリスクもあるので、とりあえず3程度で。安全なのはもちろんjオプションなし。

3. AVSの認証
3.1 プロダクトの登録
amazonへサインインして今回のプロダクトを登録します。
入力方法はこちらを参考に(https://github.com/alexa/alexa-avs-sample-app/wiki/Create-Security-Profile)

この登録で設定したProductID,ClientID,ClientSecretの3つは認証時に必ず必要になるよ!

3.2 AlexaClientSDKConfig.jsonの設定
これは認証実行時に必要な情報を定義する設定ファイルです

場所:/home/pi/sdk-folder/sdk-build/Integration
ファイル名:AlexaClientSDKConfig.json

AlexaClientConfig.json
{
    "authDelegate":{
        "clientSecret”:”Amazonへ設定したClientSecret”,
        "deviceSerialNumber":"123456,(適当でいい)
        "refreshToken”:”{デフォルトの状態にしておく、認証後に自動的に追加されるため}”,
        "clientId”:”Amazonへ設定したclientID”,
        "productId”:”Amazonへ設定したproductID”
    },
    "alertsCapabilityAgent":{
        "databaseFilePath":"/home/pi/sdk-folder/application-necessities/alerts.db",
        "alarmSoundFilePath":"/home/pi/sdk-folder/application-necessities/sound-files/med_system_alerts_melodic_01._TTH_.mp3",
        "alarmShortSoundFilePath":"/home/pi/sdk-folder/application-necessities/sound-files/med_system_alerts_melodic_01_short._TTH_.wav",
        "timerSoundFilePath":"/home/pi/sdk-folder/application-necessities/sound-files/med_system_alerts_melodic_02._TTH_.mp3",
        "timerShortSoundFilePath":"/home/pi/sdk-folder/application-necessities/sound-files/med_system_alerts_melodic_02_short._TTH_.wav"
    },
    "settings":{
        "databaseFilePath":"/home/pi/sdk-folder/application-necessities/settings.db",
        "defaultAVSClientSettings":{
            "locale":"ja-JP"
        }
    },
    "certifiedSender":{
        "databaseFilePath":"/home/pi/sdk-folder/application-necessities/certifiedSender.db
    }
}

3.3 認証
認証用プログラムを起動、3000ポートで待ち受けます
cd /home/pi/sdk-folder/sdk-build && python AuthServer/AuthServer.py

ブラウザを立ち上げhttp://localhost:3000へアクセス
Developer用のアカウントを聞かれるのでログイン
ログインが成功するとWindowを閉じろというメッセージが出て認証完了

※AlexaClientSDKConfig.jsonのrefreshTokenに新たなトークンが追加されていることが確認できます。

4 実行
4.1 マイクのテスト
テストの前にpiのカレントに設定ファイルを用意します。

ファイル名:.asoundrc
場所:ユーザーカレントディレクトリ

.asoundrc
pcm.!default{
    type asym
    playback.pcm {
        type plug
        slave.pcm "hw:0,0"
    }
    capture.pcm {
        type plug
        slave.pcm "hw:1,0"
    }
}

※playbackは再生、captureは入力の設定ブロックになっている。
slave.pcmの値hw:はa,b a=カード b=デバイス番号となっている。
ラズパイに差したスピーカーとマイクの値を確認し設定すること。
aplay -lで確認できる。

4.2 soxのインストール
音声の加工や編集が出来るコマンドですー。
sudo apt-get install sox -y

4.3 マイクとスピーカーの入出力テスト
rec test.wav

実行したら何か話してみよう。
声に合わせて入力ボリュームが変化している様子がコマンドから分かると思う。
それが確認できたらControl+Cで終了

`aplay /usr/share/sounds/alsa/Front_Center.wav'

「フロントセンタ〜」っていう女性の声が聞こえたらOK
もし聞こえない場合はスピーカーの接続種別により次の設定を行って下さい

sudo amixer cset numid=3 x

xは接続の種類です。
0:自動判別
1:ライン入力(3.5mm)
2:HDMI
自動判別の場合はHDMIが優先されます。

4.4 いよいよAlexa起動
srcに移動
cd /home/pi/sdk-folder/sdk-build/SampleApp/src
SampleAPPを起動

TZ=UTC ./SampleApp /home/pi/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.json /home/pi/sdk-folder/third-party/alexa-rpi/models

SampleAPPの引数に設定ファイルであるAlexaClientSDKConfig.jsonとmodelsを指定

4.5 「Alexa! こんにちは!」と話しかけてみよう。
あとは、スマホにAlexa APPを追加するかここから好きなスキルを追加してみましょう。

カスタムスキルの作り方(Alexa Skills KitとLambda)はいろんな人が書いてるのでそちらを見てください。