AVS Device SDKを動かしてみる anchor.png

Amazon Alexaを動かすにはいくつかのやり方があるようだ。

  • alexa-avs-sample-app
    Javaで作成されているフロントエンドアプリ。GUI環境が必要。
    (いつの間にか,公開されなくなってしまった。)
  • avs-device-sdk
    C++で作成されているアプリ。製品なんかに組み込む用途向けらしい。CUI環境のみで動作する。
    (月1回のペースで更新されているようだ。)

このページでは, AVS Device SDK を手持ちのAIY Voice Kitを載せているRaspberry Pi 3Bで,試してみることにした。

AVS Device SDKをRaspberry Piにインストールする手順は,https://github.com/alexa/avs-device-sdk/wiki/Raspberry-Pi-Quick-Start-Guide に書かれている。

AVSは,Alexa Voice Serviceのこと。

Page Top

準備 anchor.png

ホームにsdk-folderを作成する。

$ cd /home/yuji/
$ mkdir sdk-folder
$ cd sdk-folder
$ mkdir sdk-build sdk-source third-party application-necessities
$ cd application-necessities
$ mkdir sound-files
Page Top

サウンドdriverとalsa,pulseaudioの設定 anchor.png

AIY Voice Kit(V1になった古いやつ) をRaspberry Pi 3Bに乗っけた物があるので,それにAVSを動かすようにしてみた。

/boot/config.txtでのサウンドdriverをロードする部分を,AIY Voice Kitのみ使うようにしてみる。

# Enable audio (loads snd_bcm2835)
#dtparam=audio=on
#dtoverlay=i2s-mmap
dtoverlay=googlevoicehat-soundcard

このように修正して,Raspberry Piのオンボードのサウンド機能をoffにして,AIY Voice KitのVoice HATのみを使えるようにする。

alsaの設定ファイルを,AIY Voice Kitのマイクとスピーカーを使用するようにする。
/etc/asound.confを以下の内容にする。

options snd_rpi_googlemihat_soundcard index=0

pcm.softvol {
    type softvol
    slave.pcm dmix
    control {
        name Master card 0
    }
}

pcm.micboost {
    type route
    slave.pcm dsnoop
    ttable {
        0.0 30.0
        1.1 30.0
    }
}

pcm.!default {
    type asym
    playback.pcm "plug:softvol"
    capture.pcm "plug:micboost"
}

ctl.!default {
    type hw
    card 0
}

そして,~/.asoundrcにコピーしておく。

$ cp /etc/asound.conf ~/.asoundrc

AVS Device SDKは,PulseAudioを使用してはいないようだ。また,Raspbianを更新したらPulseAudioが起動しなくなっていた。

しかし,AVSを動かす時に音関連はPulseAudio経由で行うことにする。
なので,PulseAudioの設定ファイル/etc/pulse/default.paを設定しておく。

load-module module-alsa-sink device=dmix
load-module module-alsa-source device=dsnoop 
#load-module module-alsa-source device=hw:0,0
 :
 :
# comment out by Yuji Ueno
### Automatically load driver modules depending on the hardware available
#.ifexists module-udev-detect.so
#load-module module-udev-detect
#.else
# Use the static hardware detection module (for systems that lack udev support)
# comment out by Yuji Ueno
#load-module module-detect
#.endif

このようにして,PulseAudioからALSAライブラリ(dmix/dsnoopプラグイン使用)経由でサウンドを使用するようにする。
また,udevによる自動でサウンドドライバーをロードしないようにしておく。(起動時にロードするので)

Raspberry Piをリブート後,pacmdを使って,音量とマイク入力レベルの調整をしておく。pacmdを使うのは,amixerだとマイク入力を100%以上に設定できないため。

$ pacmd set-sink-volume alsa_output.dmix 0x6667
$ pacmd set-source-volume alsa_input.dsnoop 0x15000

マイク入力レベルを上げるのは,最近のStretchだとなぜかマイク感度が凄く低くなってしまったため。(おそらく,AIY Voice KitのVoice HATのドライバーの設定だとは思うが,対応方法がわからなかった。)

Page Top

依存関連をインストール anchor.png

AVS Device SDKは,いくつかのライブラリやツールを必要とするので,それをインストールする。

$ sudo apt-get 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

マイクを使用するのにPortAudioを使用するので,ダウンロードしてビルドしておく。

$ cd ~/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

commentjsonは,AlexaClientSDKConfig.jsonをパースするのに必要。 commentjsonを以下のようにしてインストールする。

$ pip install commentjson
Page Top

AVS Device SDKとWakeWordエンジン(音声トリガー)をダウンロードする anchor.png

Alexaは,話しかけた言葉に反応するようなシステム。その話しかけた言葉を認識するシステムがWakeWordエンジンって言うみたい。
上記のサイトには,以下のようにAVS Device SDKとWakeWordエンジンにはSensoryをインストールしろと書いてある。

  1. AVS Device SDKをsdk-sourceにクローンする
    $ cd ~/sdk-folder/sdk-source
    $ git clone git://github.com/alexa/avs-device-sdk.git
  2. Sensory's WakeWord Engineをthird-partyにクローンする
    $ cd ~/sdk-folder/third-party
    $ git clone git://github.com/Sensory/alexa-rpi.git
  3. Sensory's WakeWord Engineを動かすためのライセンスを取得する:
    $ cd ~/sdk-folder/third-party/alexa-rpi/bin/
    $ ./license.sh

しかし今回は,WakeWordを認識するプログラムをSensoryではなく Snowboy を利用する。
変える理由は,デフォルトのSensoryだと,WakeWord認識時のマイク感度を調整出来ないのと,使用できるライセンスが時限(3ヶ月)があるため。また,Snowboyだと,「アレクサ」って呼びかける言葉も任意の言葉に変えられるみたい。

AVS Device SDKとSnowboyをダウンロードし,その依存パッケージを追加する。

  1. AVS Device SDKをsdk-sourceにクローンする
    $ cd ~/sdk-folder/sdk-source
    $ git clone git://github.com/alexa/avs-device-sdk.git
    上と同じ
  2. Snowboyを取得する。
    $ cd ~/sdk-folder/third-party
    $ git clone https://github.com/Kitt-AI/snowboy.git
    Snowboyはコンパイル済みのバイナリ供給のようだ。
  3. Snowboyが必要とするライブラリをインストールする。
    $ sudo apt-get install libatlas-base-dev

Snowboyのリソースファイル(「アレクサ」に反応する)をセットしておく。

$ cd ~/sdk-folder/third-party/snowboy/resources
$ cp alexa/alexa-avs-sample-app/alexa.umdl .
Page Top

AVS Device SDKのビルド anchor.png

Page Top

Makefileを作成 anchor.png

ビルドするには,まずcmakeでMakefileを作成しろと書いてある。

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

Snowboyにするため,以下のように変更してcmakeでMakefileを作成した。

$ cd ~/sdk-folder/sdk-build
$ cmake ~/sdk-folder/sdk-source/avs-device-sdk -DKITTAI_KEY_WORD_DETECTOR=ON -DKITTAI_KEY_WORD_DETECTOR_LIB_PATH=~/sdk-folder/third-party/snowboy/lib/rpi/libsnowboy-detect.a -DKITTAI_KEY_WORD_DETECTOR_INCLUDE_DIR=~/sdk-folder/third-party/snowboy/include -DGSTREAMER_MEDIA_PLAYER=ON -DPORTAUDIO=ON -DPORTAUDIO_LIB_PATH=~/sdk-folder/third-party/portaudio/lib/.libs/libportaudio.a -DPORTAUDIO_INCLUDE_DIR=~/sdk-folder/third-party/portaudio/include
Page Top

AVS Device SDKをビルド anchor.png

後は,SDK Sampleアプリをビルドする。

$ cd ~/sdk-folder/sdk-build
$ make
Page Top

Snowboy関連でビルドエラー anchor.png

SDK Sampleアプリをビルドしようとすると,Snowboy関連でビルドエラーになった。
最近更新されているソース(v1.11.0)だと,どのバージョンからかわからないけど修正されていたので,以下は必要なくなった。

以下のように修正した。

~/sdk-folder/sdk-source/avs-device-sdk/KWD/KittAi/src/KittAiKeyWordDetector.cpp

std::chrono::milliseconds msToPushPerIteration) :
        AbstractKeywordDetector(keyWordObservers, keyWordDetectorStateObservers),
        m_stream{stream},
            m_maxSamplesPerPush{(audioFormat.sampleRateHz / HERTZ_PER_KILOHERTZ) * static_cast<unsigned int>(msToPushPerIteration.count())}{

と,static_castを追加。

それと,~/sdk-folder/sdk-source/avs-device-sdk/build/cmake/BuildOptions.cmake

add_definitions (-D_GLIBCXX_USE_CXX11_ABI=0)

を,

# Set up the compiler flags.

の下あたりに追加。

再度,makeでビルドする。

Page Top

設定ファイルを編集 anchor.png

Amazon開発者コンソール(USAのAmazon)でAVS Device SDK用にデバイス登録(製品登録)する。

情報の登録:

  • 製品名
    好きな名前で良い。AIYVoiceKit
  • 製品ID
    好きなIDで良い。AIYVoiceKit
  • 製品タイプ
    Alexa内臓の端末。
  • ご使用の端末は、コンパニオンアプリを使用しますか~ はい
  • 商品カテゴリ
    ワイヤレススピーカー
  • 製品概要
    なんでもよい。Raspberry Pi Sample Project
  • 画像をアップロード
    未登録。
  • エンドユーザーは、商品とどのようにやり取りするのでしょうか
    ハンズフリーなのかも。ファーフィールドにしてみた。
  • この製品を商品として配信する予定ですか ?
    いいえ。
  • お客様の端末は以下のために使用されますか Alexa for Business?
    いいえ。
  • お客様の端末は以下のために使用されますか: Alexaモバイルアクセサリー プロトコルですか?
    いいえ。

セキュリティプロファイル:
情報と同じに登録した。
ウェブのところのクライアントIDをメモしておく。

こんなように登録してみた。

登録した情報を,~/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.jsonファイルにをセットする。

{
    "deviceInfo":{
        "clientId":"amzn1.application-oa2-client.xxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "deviceSerialNumber":"yyyyyy",
        "productId":"AIYVoiceKit"
    },
    "alertsCapabilityAgent":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/alerts.db"
    },
    "certifiedSender":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/certifiedSender.db"
    },
    "settings":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/settings.db",
        "defaultAVSClientSettings":{
            "locale":"ja-JP"
        }
    },
    "notifications":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/notifications.db"
    },
    "cblAuthDelegate":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/cblAuthDelegate.db"
    },
    "dcfDelegate":{
    },
    "miscDatabase":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/miscDatabase.db"
    },
    "sampleApp":{
        "endpoint": "https://avs-alexa-fe.amazon.com",
        "displayCardsSupported":true
    },
    "gstreamerMediaPlayer":{
        "audioSink":"alsasink"
    }
}

deviceInfoのclientId,deviceSerialNumber,productIdを設定する。
それぞれ,Amazon開発者コンソールで作成したデバイスの内容を設定するんだけど,deviceSerialNumberは,なんでも良いみたいなんで,123456789にした。

Locale設定を,ja-JPにしておく。

エンドポイント を,日本の https://avs-alexa-fe.amazon.com にする。

それと,dbファイル名を任意の場所に指定する。

バージョンが更新されて,以下のエントリが必要になった。

    "deviceSettings":{
        "databaseFilePath":"/home/yuji/sdk-folder/application-necessities/deviceSettings.db"
    },
Page Top

SDKの起動とオプション anchor.png

公式手順では,起動時コマンドとして,以下のように書いてある。

$ cd ~/sdk-folder/sdk-build/SampleApp/src && TZ=UTC ./SampleApp ~/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.json ~/sdk-folder/third-party/alexa-rpi/models

最後の引数が,WakeWord認識プログラム用みたいなんで,これをSensoryからSnowboyに変更する。
そのため,以下のように変更して実行する。

$ cd ~/sdk-folder/sdk-build/SampleApp/src && TZ=UTC ./SampleApp ~/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.json ~/sdk-folder/third-party/snowboy/resources/

snowboyのresouucesというフォルダを参照するようにすればいいようだ。

Page Top

アプリの認証 anchor.png

起動すると,

##################################
#       NOT YET AUTHORIZED       #
##################################
 ######################################################################################
#       To authorize, browse to: 'https://amazon.com/us/code' and enter the code: {XXXX}         ######################################################################################

こんなメッセージが出るので,WEBブラウザで https://amazon.com/us/code にアクセスして自分のアカウントでログインした後,SDK SampleAppを実行した時に表示される認証コードを入力する。

承認されれば,SampleAppがauthorizedになって,少し経つとidle状態になる。

########################################
#       Alexa is currently idle!       #
########################################

これで,「アレクサ」って言ったら,応答してくれたら成功なんだけど・・・

Page Top

音声がスピーカーから出力されない anchor.png

しかし,「アレクサ」っていうと反応はしているようだが,音がなぜか出ない。

~/sdk-folder/sdk-source/avs-device-sdk/MediaPlayer/src/MediaPlayer.cppの以下の行が,(新しいバージョンだと,~/sdk-folder/sdk-source/avs-device-sdk/MediaPlayer/GStreamerMediaPlayer/src/MediaPlayer.cppにソースファイルが変更されている)

        MEDIAPLAYER_AUDIO_SINK_KEY, &audioSinkElement, "autoaudiosink");

のようになっているのを,

        MEDIAPLAYER_AUDIO_SINK_KEY, &audioSinkElement, "alsasink");

に変更して再ビルドしたら,音が出た。

Locale設定を日本語にしているんで大丈夫と思うが,もし英語で応答してきた場合は,c<ret>,1<ret>,6<ret>として,Localeをja_JPの日本語に設定できる。以後は日本語で応答してくれる。

Page Top

マイク感度と音声ボリュームの変更 anchor.png

デフォルト状態だとマイク感度が低すぎて,「アレクサ」になかなか反応しない。それに対して,しゃべる音声がめちゃくちゃ大きい。

マイク感度と音声のボリュームは,ソースに値が決め打ちされている。
~/sdk-folder/sdk-source/avs-device-sdk/KWD/KWDProvider/src/KeywordDetectorProvider.cppを,

/// The sensitivity of the Kitt.ai engine.
static const double KITT_AI_SENSITIVITY = 0.6;

/// The audio amplifier level of the Kitt.ai engine.
static const float KITT_AI_AUDIO_GAIN = 2.0;

と,ハードコーティングされている。
KITT_AI_SENSITIVITYでWakeWord検知でのマイク感度,KITT_AI_AUDIO_GAINで音声の大きさを設定できるみたい。

/// The sensitivity of the Kitt.ai engine.
static const double KITT_AI_SENSITIVITY = 0.70;

/// The audio amplifier level of the Kitt.ai engine.
static const float KITT_AI_AUDIO_GAIN = 0.5;

にして,再ビルド。Snowboyの開発者のページには,0から1の間の値を使えと書いてある。

マイク感度を上げすぎると,スピーカーでの音声出力を拾ったり周りの音に反応したりする。Speaking状態の時はマイクはオフじゃないのかな・・・

残念ながら,AVS Device Kitに含まれるWakeWordエンジンのSensoryやSnowboyには,スピーカーからの音声をマイクで拾った音からキャンセルする仕組み(アコースティックエコーキャンセレーション AEC)や,ビームフォーミングって呼ばれている,ある方向からのユーザー音声を拡大しつつ,他の方向からの干渉を抑える信号処理技術なんかが,入っていないようだ。

Amazonで販売されているAVS Development Kitや製品のAmazon Echoなんかは,これらの機能が入っているんで問題ないんだろうな。

もう少し何とかならないかな?

Page Top

ちょっと追加 anchor.png

現状だと,「アレクサ」って言ったときに,Listeningモードになったかどうかが画面以外からはわからない。これは,Raspberry PiにAIY Voice Kitなんでダンボール箱だけで,画面なんかが無いから。
そこで,Listeningモードになったら,ポーンというような音で知らせるようにしてみた。さらに,ボタンのランプも点灯させたみた。

~/sdk-folder/sdk-source/avs-device-sdk/SampleApp/src/UIManager.cppに,

        switch (m_dialogState) {
            case DialogUXState::IDLE:
                system("gpio -g mode 25 out");
                system("gpio -g write 25 0");
                ConsolePrinter::prettyPrint("Alexa is currently idle!");
                return;
            case DialogUXState::LISTENING:
                system("gpio -g mode 25 out");
                system("gpio -g write 25 1");
                system("aplay /home/yuji/sdk-folder/third-party/snowboy/resources/dong.wav 1>/dev/null 2>/dev/null ");
                ConsolePrinter::prettyPrint("Listening...");

と追加した。wavファイルは,Snowboyのresourceフォルダにあったファイルにしている。

Page Top

Amazon Alexaの設定 anchor.png

WEBブラウザで https://alexa.amazon.co.jp/ にアクセスしてAlexaの設定を行う。(もしくはAndroid端末のAlexaアプリで)

  • デバイスの所在地
  • デバイスのタイムゾーン
  • 温度の単位
  • 距離の単位

なんかを設定しておく。天気とか尋ねると,設定した場所について教えてくれるようになる。

Page Top

起動時に自動実行する anchor.png

起動スクリプトを作成する。
~/startavs.sh

#!/bin/bash

pulseaudio -k
pulseaudio -D
pacmd set-sink-volume alsa_output.dmix 0x6667
pacmd set-source-volume alsa_input.dsnoop 0x15000
cd ~/sdk-folder/sdk-build/SampleApp/src && TZ=UTC ./SampleApp ~/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.json ~/sdk-folder/third-party/snowboy/resources/

PulseAudioがRaspbianを更新したら起動しなくなったんで,起動するようにして,マイク感度を,pacmdで上げている。

実行パーミッションを立てる。

$ chmod 755 startavs.sh

cronを使って,Raspberry Piが起動時にAVS Device SDKのSampleAppを動かすようにする。

$ crontab -e
@reboot           /home/yuji/startavs.sh

これで,Raspberry Piを再起動したら自動的にSampleAppが動くはずなんだけど,なんとRaspberry Piがしばらく反応しなくなってしまい(1分程度),その後,勝手にシステム(OOM killer)に殺されてしまっていた [worried] 結果,SampleAppは動作しない状態に・・・

あまり上手い方法ではないけど以下のように,~/sdk-folder/sdk-source/avs-device-sdk/SampleApp/src/UserInputManager.cppを修正してみた。

    while (true) {
       
       // add by Yuji Ueno
       std::this_thread::sleep_for(std::chrono::hours(1));
       continue;
       //
       
       char x;

入力をスキップするコードを追加した。

SampleAppは起動するとユーザーからの入力をstdinから行うようになっているがデーモンのようにバックグラウンドでstdin無しで動かすと入力に失敗して,これが原因でメモリーを食いつぶしてしまっているようだ。

しょうがないんだが,ユーザー入力を受け付けないように変更した。まあインターラクティブに操作することはしないからこれでいいかな。(これを行う前に日本語ja_JPに設定しておくのを忘れないようにする。)

再度ビルドしたら,無事cronで起動時に自動的に実行できるようになった。

Page Top

Amazon Musicが使えない anchor.png

AVS Device SDKのSampleAppだと,なんとAmazon Musicを聞くことは出来ない。あくまでサンプルとしての提供とのこと。それにしても,これは辛いなぁ ;(

Fire TV Stickともつながらないし・・・

って,以前はつながらなかったんだけど,Fire TV Stick(使っているのはリモコンに音声検索できない古いタイプ)がいつの間にかAlexaが使用できるようになっていたんで,ひょっとしたらと思いAVS Device SDKを更新したら,Fire TV Stickが反応した ;)

あとは,Amazon Musicが使えればなぁ・・・


コメント一覧

新しくコメントをつける

題名
ゲスト名   :
投稿本文
より詳細なコメント入力フォームへ

Front page   Freeze Diff Backup Copy Rename Reload   New Page Page list Search Recent changes   Help   RSS of recent changes (RSS 1.0) RSS of recent changes (RSS 2.0) RSS of recent changes (RSS Atom)
Counter: 4298, today: 2, yesterday: 4
Last-modified: 2018-05-06 (Sun) 13:26:45 (JST) (703d) by yuji
ユーザ名:

パスワード:



パスワード紛失

新規登録