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

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

# この記事でわかること
- この記事だけで、GoogleHomeとAmazonEcho **２種類の開発の雰囲気がわかります** 。


<img src="https://qiita-image-store.s3.amazonaws.com/0/62822/0131b648-30de-ee94-0f55-5aceecd78a48.png" height=200 > <img src="https://qiita-image-store.s3.amazonaws.com/0/62822/e89d73e5-fe39-a2e3-4620-846d4da064bb.png" height=200 >

# 今回作るもの
- 〇〇を再生して、という非常に単純なもの
- 実際に作ったものは「[異次元のフライパン](https://www.amazon.co.jp/dp/B07CT4HQ1M/ref=sr_1_1?s=digital-skills&ie=UTF8&qid=1526634866&sr=1-1&keywords=%E3%83%95%E3%83%A9%E3%82%A4%E3%83%91%E3%83%B3)」というもので、**GoogleHome + AmazonEcho**どちらもリリースしています
    - 「チャーハンを炒めて！」と言うと炒飯を炒めている音声を流すのみ!!のかんたんなアプリです。


<a href= "https://www.amazon.co.jp/dp/B07CT4HQ1M/ref=sr_1_1?s=digital-skills&ie=UTF8&qid=1526634866&sr=1-1&keywords=%E3%83%95%E3%83%A9%E3%82%A4%E3%83%91%E3%83%B3">
 <img width="749" alt="Screen Shot 2018-05-20 at 2.02.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/60f02fe7-16ea-15c0-12cf-86d212dd00c1.png"> 
</a>

リンクはこちら

- [異次元のフライパン for GoogleHome](https://assistant.google.com/services/a/uid/000000c88c90d59b?hl=ja)
- [異次元のフライパン for AmazonEcho](https://www.amazon.co.jp/dp/B07CT4HQ1M/ref=sr_1_1?s=digital-skills&ie=UTF8&qid=1526634866&sr=1-1&keywords=%E3%83%95%E3%83%A9%E3%82%A4%E3%83%91%E3%83%B3)



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

## (1)Action On Google

### Action On Googleの初期設定
- [Action On Google](https://console.actions.google.com/u/0/)に入ります

<img width="1706" alt="Screen Shot 2018-05-20 at 19.31.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/359fc416-547d-b900-f9e3-c1e35d3ee8c7.png">

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

<img width="1694" alt="Screen Shot 2018-05-20 at 19.32.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/193a8ea8-9793-780c-2852-14c2c5860ccb.png">

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


左のメニューには、

- 「セットアップセクション」
- 「ビルドセクション」
- 「テストセクション」
- 「デプロイセクション」
- 「計測セクション」
- 「詳細設定セクション」
 
があります。
 
ひとまず、「セットアップセクション」で言語設定と呼び出しの設定を行ってください。

<img width="1697" alt="Screen Shot 2018-05-20 at 19.33.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/3d27c39f-cd7e-e3c9-658c-63bde52927f5.png">


<img width="1696" alt="Screen Shot 2018-05-20 at 19.33.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/344c8d4d-da5d-2062-6ca6-46e64ec2e869.png">



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


<img width="682" alt="Screen Shot 2018-05-20 at 19.34.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/6d48f8d9-8b87-e449-bb38-717951b595cf.png">

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

## (2)DialogFlowで、音声の返しなどをカスタムする
今回は、音声を流すのみですので、DialogFlowを使用します。

<img width="1407" alt="Screen Shot 2018-05-20 at 19.35.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/c0cee2f1-9aed-0bdd-6a17-bfcb60e39dff.png">

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


<img width="1550" alt="Screen Shot 2018-05-20 at 19.35.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/60a81fa6-b23a-345a-9308-7a736fda4dcb.png">

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

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

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

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

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

<img width="1327" alt="Screen Shot 2018-05-20 at 20.01.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/a87b3bbd-b542-1142-bb8f-f73a86c41a5b.png">

<img width="1333" alt="Screen Shot 2018-05-20 at 20.06.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/c2cc7575-5186-6099-7374-c6571cf1bd71.png">

こんな感じですね

### Intentの設定
Intentはデフォルトで２つ用意されています。

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

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

<img width="1550" alt="Screen Shot 2018-05-20 at 19.35.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/fc58f610-aa49-6ecf-8cd2-00ab1d0024d8.png">

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

<img width="1316" alt="Screen Shot 2018-05-20 at 20.02.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/ecfef589-1a40-976f-50fd-e2dc089d0469.png">

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

<img width="1025" alt="Screen Shot 2018-05-20 at 20.02.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/ed569da6-ec96-ac5f-9277-9a75fdb41c09.png">

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

### あとは、テストをしていい感じにdeploy（申請）するだけ！！
- deployの項目に、説明や画像やプライバシーポリシーなどのリンクを貼る場所があるので、いい感じ整えれば申請できます！

<img width="1534" alt="Screen Shot 2018-05-21 at 1.04.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/0cfe82aa-0275-9ce1-f3b3-8de295ef259d.png">


## (3)GoogleHomeまとめ
- 使用したサービス **Action On Google** と **DialogFlow**
- 音声を流す程度であれば、特にコーディングが必要ない
- ボタン操作で基本的に終わる

# **AmazonEchoの場合**
- 音声を再生させるだけであっても、Alexaのスキルは、コーディングを必要とします。
- **AlexaConsole**でAlexaスキルの基本設定を行い、**AWS　Lambda**で音声を流す制御などをします。
    - 今回、AWS Lambdaをデプロイする方法として、Serverless Frameworkというものも一緒に使いました。
        - [Serverless Framework](https://github.com/serverless/serverless)を使うことによって、Lambdaの設定をコードで管理できます


## (1)Alexaスキル開発の準備
### アカウントの用意
- GoogleのようにGoogleアカウントのみでは開発できません

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

#### **AmazonDeveloperアカウント**
- AmazonDeveloperConsoleでスキルの管理を行います

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

## (2)AlexaConsole
- [AlexaConsole](https://developer.amazon.com/alexa/console/ask)にログインします
- スキルの作成を押してください

<img width="943" alt="Screen Shot 2018-05-20 at 22.21.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/1fda0173-2e5d-98ed-81d4-0171f481272a.png">

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

<img width="1244" alt="Screen Shot 2018-05-20 at 22.27.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/96cf3133-e15b-1d6a-a6b8-63aec1982e4e.png">

### 設定していく
#### はじめに「呼び出し名」を決めてあげます。
##### **注意点**（ここで結構ハマりました）
- **1単語だけの呼び出し名は使用できない**（ただし、その単語が自分のブランド/知的財産である場合、または1単語が複数の単語を組み合わせたものの場合は例外）。  
- **日本語の呼び出し名は2つの名詞を含む必要がある。**

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

<img width="1684" alt="Screen Shot 2018-05-20 at 22.27.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/64faaeda-38d1-4cc9-35cf-e99bd89f3860.png">

#### 次にカスタムインテントを作成します
- GoogleHomeと同じであらゆるパターンを列挙します

<img width="1307" alt="Screen Shot 2018-05-20 at 22.28.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/318c6019-0c89-e510-1af0-ce6306b72a66.png">

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

<img width="1631" alt="Screen Shot 2018-05-20 at 22.28.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/1577c410-9d77-d533-8be0-683a07649ef7.png">


#### AudioPlayerを有効にする
- インターフェースの Audio playerを有効にしておきます
![image.png](https://qiita-image-store.s3.amazonaws.com/0/62822/3e5fcdfe-3a2f-cda3-704e-b635e1b3b440.png)


## (3)AWS Lambda関数をデプロイする
AWS Lambdaのデプロイには、[ServerlessFramework](https://github.com/serverless/serverless)を使いました

### 構成はこんな感じ
```
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らへん）
- ５回ほどリジェクトをくらったので、その文をいくつか貼っておきます

```
1.   スキルは、呼び出し名の要件 #2を満たしていません。1単語だけの呼び出し名は使用できません（ただし、その単語が自分のブランド/知的財産である場合、または1単語が複数の単語を組み合わせたものの場合は例外です）。   また、日本語の呼び出し名は2つの名詞を含む必要があります。2つの名詞を組み合わせた呼び出し名に変更し、新しい呼び出し名が、スキルのサンプルフレーズ、スキルの説明、スキルの応答（あれば）で実際に使われていることを確認してください。
 
2.   スキルを確実に起動させ、多くのユーザーのリクエストに対応するためには、ユーザーが発話する可能性のある発話をサンプル発話に追加する必要があります。サンプル発話に追加されていないものをユーザーが発話した場合、スキルが確実に起動しない可能性があります。 スキル説明に記載があり、ユーザーが発話する可能性が非常に高いので、以下の発話をサンプル発話に追加するようお願いします。 

繰り返して 
最初から
 

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

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

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

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

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

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

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

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

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

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


# 参考
- 大変参考になりました、ありがとうございました！！
- http://techblog.kayac.com/lets-make-alexa-skill-2017
- https://qiita.com/donchan922/items/4d499bfa8d72981702be
- https://qiita.com/yanosen_jp/items/5745a6c6dc5aba2cba58
- https://dev.classmethod.jp/voice-assistant/amazon-alexa/firststep-alexa-skil-develop1/

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

## 表にまとめてみる
|  | AmazonEcho | GoogleHome |
|:--|:--:|:--:|
| 管理画面の使いやすさ | △ <br> ちょっとわかりずらい-1 | -  <br> 普通に使えそう |
| 開発のし易さ | ◎ <br> Lambda nodejsいいね+2 | ○ <br> DialogFlowかっこいい+1 |
| ドキュメント量やわかり易さ | △ <br> もう一声欲しい-1 | -  <br> 今後に期待 |
| 審査の厳しさ | -  <br> まあまあ厳しい | ○ <br> よしなになってくれるところが多いので、通るわなという印象+1 |
| テスト | △ <br> 音声周りができない-1 | -  <br> 許可するダイアログではまったがいい感じ |
| その他 | △ <br> 呼び出し名詞問題で-1 | × <br> ok googleがながい-３ |
| **合計得点** | **-2** | **-1** |

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

# 評価など
- 全然意味わからないけど評価が高いｗ（頼んでないし、誰かわからない）ありがとうございますｍ＞＜ｍ

```
異次元の真骨頂！

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

発想が異次元

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

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