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が使えればなぁ・・・


新しくコメントをつける

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

トップ   凍結 差分 バックアップ 複製 名前変更 リロード   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom
Counter: 1911, today: 1, yesterday: 0
最終更新: 2020-12-26 (土) 16:07:50 (JST) (1211d) by yuji