AWS
Alexa
serverless
GoogleHome
スマートスピーカー

「GoogleHome」と「AmazonEcho」を表で比較する

GoogleHomeとAmazonEchoで同じアプリを作って比較しました!
今回は、音声を再生するだけのアプリですがいろいろなハマリポイントなどあったので、それも含めて記事にできればと思います。

この記事でわかること

  • この記事だけで、GoogleHomeとAmazonEcho 2種類の開発の雰囲気がわかります

今回作るもの

  • 〇〇を再生して、という非常に単純なもの
  • 実際に作ったものは「異次元のフライパン」というもので、GoogleHome + AmazonEchoどちらもリリースしています
    • 「チャーハンを炒めて!」と言うと炒飯を炒めている音声を流すのみ!!のかんたんなアプリです。


Screen Shot 2018-05-20 at 2.02.01.png

リンクはこちら

GoogleHomeの場合

  • 音声を再生させるだけであれば、GoogleHomeアプリは、コーディングなしで完結します。
  • ActionOnGoogleでGoogleHomeアプリの基本設定を行い、DialogFlowで音声を流す制御などをします。
    • 今回は使用してないですが、もっと複雑な処理をしたい場合は、FirebaseFunctions を使用します

(1)Action On Google

Action On Googleの初期設定

Screen Shot 2018-05-20 at 19.31.57.png

  • 「Add/import project」 を選択します

Screen Shot 2018-05-20 at 19.32.38.png

  • するとWelcomeページが表示されるので、一旦右上のskipに進みます

左のメニューには、

  • 「セットアップセクション」
  • 「ビルドセクション」
  • 「テストセクション」
  • 「デプロイセクション」
  • 「計測セクション」
  • 「詳細設定セクション」

があります。

ひとまず、「セットアップセクション」で言語設定と呼び出しの設定を行ってください。

Screen Shot 2018-05-20 at 19.33.06.png

Screen Shot 2018-05-20 at 19.33.22.png

Actionを設定

スマートスピーカに欠かせない、要望に何かをする中心部分の機能を作成します
- 「ビルドセクション」のActionを選択し、Actionを作成しましょう

Screen Shot 2018-05-20 at 19.34.13.png

  • Custom intentを選択し「Build」を押します。すると、「DialogFlow」の認証からDialogFlowのページが現れます。

(2)DialogFlowで、音声の返しなどをカスタムする

今回は、音声を流すのみですので、DialogFlowを使用します。

Screen Shot 2018-05-20 at 19.35.27.png

まずは、名前、言語とタイムゾーンを設定してCREATEすると

Screen Shot 2018-05-20 at 19.35.50.png

DialogFlowのメニューが左に表示されます。

Entityを設定

ここで先に、「Entity」を作成します

今回このアプリで必要なのは

  • 「炒飯」
  • 「炒めて」
  • 「フライパン」

この3つを聞き取らないといけないのですが、「炒める」「炒めて」「作って」「料理して」などは同じ処理をしたいので、Entityとしてまとめて定義しておきます。

Screen Shot 2018-05-20 at 20.01.55.png

Screen Shot 2018-05-20 at 20.06.08.png

こんな感じですね

Intentの設定

Intentはデフォルトで2つ用意されています。

  • Fallback: 聞き取れなかった場合
  • Welcome: アプリを開くと最初に実行される

まずは、2つをいい感じの文言に設定してみてください。今回はあまりいじってません。ちょっと変えたぐらいです。

Screen Shot 2018-05-20 at 19.35.50.png

次にカスタムIntentを作成します。
今回は「フライパンでチャーハンを炒めて」というと音声を再生させたいので、先程作成したEntityを使って、あらゆるパターンを定義しておきます。

Screen Shot 2018-05-20 at 20.02.27.png

下の方にResponceがあるので、そこには、speak タグというものが用意されているのでその中に audio タグで音声を再生させるためのURLを記入します。
これは、SSMLと言って、Speech Synthesis Markup Languageの略だそうです。
https://developers.google.com/actions/reference/ssml

Screen Shot 2018-05-20 at 20.02.39.png

<speak>
  <audio src="hogehogehogehogoehgehogoegoehgoeo.mp3">didn't get your MP3 audio file</audio>.
</speak>

あとは、テストをしていい感じにdeploy(申請)するだけ!!

  • deployの項目に、説明や画像やプライバシーポリシーなどのリンクを貼る場所があるので、いい感じ整えれば申請できます!

Screen Shot 2018-05-21 at 1.04.26.png

(3)GoogleHomeまとめ

  • 使用したサービス Action On GoogleDialogFlow
  • 音声を流す程度であれば、特にコーディングが必要ない
  • ボタン操作で基本的に終わる

AmazonEchoの場合

  • 音声を再生させるだけであっても、Alexaのスキルは、コーディングを必要とします。
  • AlexaConsoleでAlexaスキルの基本設定を行い、AWS Lambdaで音声を流す制御などをします。
    • 今回、AWS Lambdaをデプロイする方法として、Serverless Frameworkというものも一緒に使いました。
      • Serverless Frameworkを使うことによって、Lambdaの設定をコードで管理できます

(1)Alexaスキル開発の準備

アカウントの用意

  • GoogleのようにGoogleアカウントのみでは開発できません

AWSアカウント

  • スキルはAWS Lambdaと、AlexaSkillsKitで作られるので、AWSのアカウントが必要です。

AmazonDeveloperアカウント

  • AmazonDeveloperConsoleでスキルの管理を行います

Amazonアカウント

  • echoやdotの実機でスキルを試す場合には、AmazonDeveloperアカウントと同じメールアドレスで作られたAmazonのアカウントが必要です

(2)AlexaConsole

  • AlexaConsoleにログインします
  • スキルの作成を押してください

Screen Shot 2018-05-20 at 22.21.00.png

  • 今回はカスタムを選んでください

Screen Shot 2018-05-20 at 22.27.00.png

設定していく

はじめに「呼び出し名」を決めてあげます。

注意点(ここで結構ハマりました)
  • 1単語だけの呼び出し名は使用できない(ただし、その単語が自分のブランド/知的財産である場合、または1単語が複数の単語を組み合わせたものの場合は例外)。
  • 日本語の呼び出し名は2つの名詞を含む必要がある。

当初の設計では、「チャーハンを炒めて」で起動する予定でしたが
「異次元 (名詞) すぎるフライパン (名詞2) でチャーハンを炒めて (intent) 」としました

Screen Shot 2018-05-20 at 22.27.50.png

次にカスタムインテントを作成します

  • GoogleHomeと同じであらゆるパターンを列挙します

Screen Shot 2018-05-20 at 22.28.11.png

エンドポイントの設定(あとで)

  • エンドポイントを設定します。AWS Lambdaを使っているのでそのARNを入力しますが、まだLambda関数を作成していないので、一旦紹介まで

Screen Shot 2018-05-20 at 22.28.36.png

AudioPlayerを有効にする

  • インターフェースの Audio playerを有効にしておきます image.png

(3)AWS Lambda関数をデプロイする

AWS Lambdaのデプロイには、ServerlessFrameworkを使いました

構成はこんな感じ

serverless.yml
handler.js
あとは適当にintent.jsonとかもgit管理してる
serverless.yml
service: FriedRice

provider:
  name: aws
  runtime: nodejs6.10
  profile: alexa
  stage: production
  region: ap-northeast-1

functions:
  friedSound:
    handler: handler.main
    events:
      - alexaSkill

handler.js
'use strict';

const Alexa = require('alexa-sdk');

const APP_ID = "amzn1.ask.skill.hogehogehogoehgoehgegeog";

const handlers = {
    'LaunchRequest': function () {
        this.emit('PlayAudio');
    },
    'PlayAudioIntent': function () {
        this.emit('PlayAudio');
    },
    'PlayAudio': function () {
        const audioUrl = 'https://s3-ap-northeast-1.amazonaws.com/hosgehgoehgoehgoeoge.mp3';
        this.response.audioPlayerPlay('REPLACE_ALL', audioUrl, audioUrl, null, 0);
        this.emit(':responseReady');
    },
    'play': function () {
        this.emit('PlayAudio');
    },
    'AMAZON.ResumeIntent': function () {
        this.emit('PlayAudio');
    },
    'AMAZON.PauseIntent': function () {
        this.emit('AMAZON.StopIntent');
    },
    'AMAZON.CancelIntent': function () {
        this.emit('AMAZON.StopIntent');
    },
    'AMAZON.StopIntent': function() {
        this.response.audioPlayerStop();
        this.emit(':responseReady');
    },
    'AMAZON.HelpIntent': function () {
        this.emit(':tell', 'Alexaがチャーハンを作ってくれます。チャーハンを炒めてと言ってください。');
    },
    'AMAZON.NextIntent': function () {
        this.emit(':tell', 'まだ、半焼けです');
    },
    'AMAZON.StartOverIntent': function () {
        this.emit(':tell', 'そんな、もったいない');
    },
    'AMAZON.ShuffleOnIntent': function () {
        this.emit(':tell', 'たくさん炒めますね');
    },
    'AMAZON.ShuffleOffIntent': function () {
        this.emit(':tell', '控えめに炒めますね');
    },
    'AMAZON.LoopOnIntent': function () {
        this.emit(':tell', 'そんなに食べれます?');
    },
    'AMAZON.LoopOffIntent': function () {
        this.emit(':tell', '一生懸命作ります');
    },
    'AMAZON.PreviousIntent': function () {
        this.emit(':tell', '前の人のチャーハンがそんなに美味しかったですか、そうですか');
    },
    'AMAZON.RepeatIntent': function () {
        this.emit(':tell', 'たくさん食べたいんですね');
    },


    'Unhandled': function () {
        this.response.audioPlayerStop();
    },
};

module.exports.main = (event, context, callback) => {
    const alexa = Alexa.handler(event, context);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};


デプロイする

$ sls deploy -v

デプロイが終わると、ARNがわかる(TerminalもしくはLambdaの管理画面からわかる)ので、コピーして「エンドポイントの設定(あとで)」のところにペーストします

(4)Alexaスキルの申請をする

  • Alexaのテストはシュミレーターありますが、音声のテストができません。ですので私は実機を購入しました。
  • また、一時停止やリピートの機能も正常に動かないと審査を通過しません。
  • 審査は結構早く見てくれます。夜に提出すると次の日の16時には結果がかえってきました。(2018/05らへん)
  • 5回ほどリジェクトをくらったので、その文をいくつか貼っておきます
1.   スキルは、呼び出し名の要件 #2を満たしていません。1単語だけの呼び出し名は使用できません(ただし、その単語が自分のブランド/知的財産である場合、または1単語が複数の単語を組み合わせたものの場合は例外です)。   また、日本語の呼び出し名は2つの名詞を含む必要があります。2つの名詞を組み合わせた呼び出し名に変更し、新しい呼び出し名が、スキルのサンプルフレーズ、スキルの説明、スキルの応答(あれば)で実際に使われていることを確認してください。

2.   スキルを確実に起動させ、多くのユーザーのリクエストに対応するためには、ユーザーが発話する可能性のある発話をサンプル発話に追加する必要があります。サンプル発話に追加されていないものをユーザーが発話した場合、スキルが確実に起動しない可能性があります。 スキル説明に記載があり、ユーザーが発話する可能性が非常に高いので、以下の発話をサンプル発話に追加するようお願いします。 

繰り返して 
最初から


3.   カスタマーに提示された情報だけでは、スキルのコア機能を完了できませんでした。スキルの説明およびプロンプトは、ユーザーが操作しやすく、コア機能が明確にわかるものにする必要があります。 

再現手順: 
ユーザー: アレクサ、パラパラなチャーハンを開いて 
スキル: (音声再生) 
ユーザー: 最初から 
スキル: そんな、もったいない
(続きの音声) 

補足: 
ユーザーが「最初から」とリクエストしているのにもかかわらず、音声は最初から流れません。仕様を変更しないのであれば、ユーザーが「最初から」と発話しても、音声が最初から流れるわけではない旨をスキル説明に追加するようお願いします。 

また、ユーザーが「繰り返して」を発話する際も同様に修正をお願いします。


4.   スキル内の音声再生が、AMAZON.PauseIntentを呼び出した際、想定どおりに停止しません。すべての音声再生は、再生中に「一時停止」をリクエストした際、エラーを返すことなく停止するようにしてください。 

再現手順: 
ユーザー: アレクサ、パラパラなチャーハンを開いて 
スキル: (音声再生) 
ユーザー: 一時停止 
スキル: スキルからの応答に問題があります 

音声再生の要件については、申請チェックリストのテストケース3.5を参照してください。


※通常は、「起動、ヘルプ、キャンセル、停止、セッションエンドリクエスト」が必須ですが、今回はAudioPlyerを使用しているので「一時停止やリピートの機能」も必須となっています。

  • これらの問題がなければ、公開タブから申請を押すと完了です!

# リポジトリ
ここで管理しているので、参考になれば幸いです
https://github.com/okamuroshogo/FriedRice

参考

感想

  • AmazonEchoスキルを先に実装したのですが、AmazonEchoの方が大変だった印象があります。
  • 審査はどちらともちゃんと見ているようで、必ずFBがありました。

表にまとめてみる

AmazonEcho GoogleHome
管理画面の使いやすさ
ちょっとわかりずらい-1
-
普通に使えそう
開発のし易さ
Lambda nodejsいいね+2

DialogFlowかっこいい+1
ドキュメント量やわかり易さ
もう一声欲しい-1
-
今後に期待
審査の厳しさ -
まあまあ厳しい

よしなになってくれるところが多いので、通るわなという印象+1
テスト
音声周りができない-1
-
許可するダイアログではまったがいい感じ
その他
呼び出し名詞問題で-1
×
ok googleがながい-3
合計得点 -2 -1

ぎりぎりGoogleHomeのほうが勝ちだが、愛着的にはAlexaに勝って欲しかった
(手間がかかる方が愛着がでるのか)

評価など

  • 全然意味わからないけど評価が高いw(頼んでないし、誰かわからない)ありがとうございますm><m
異次元の真骨頂!

お金がなくて白米しか食べられない時に、味気なさを紛らわせればと思い使用してみました。
その瞬間、この世のモノとは思えないサウンドに驚きました。
今までいろんな異次元を体験してきましたが、まさに異次元の真骨頂!
”No 異次元 No フライパン”
ミーティング中や授業中などにも最適だと思いました。
次回作楽しみにしています。
===

発想が異次元

環境音は数多くあれどチャーハンを炒めるスキルがあっただろうか。
永続リピートのロングバージョン希望。

あとがき

  • GoogleHomeもAmazonEchoもアプリを公開できるとTシャツと無料枠がもらえるそうです!???楽しみだ。
  • HomePodも同じやつ作って検証したいとも思ってます。
  • 次はiOSアプリと連動したスキルを開発したくてしょうがないです、頑張ります。