LoginSignup
6
4

More than 5 years have passed since last update.

Amazon Echo (Alexa) スキルをノンコーディング(AzureLogicApps)で開発する

Last updated at Posted at 2019-01-01

0. はじめに

開発者待望のAlexaスキル内課金が米国で可能に!など、2019年は日本でもスマートスピーカーのスキル開発がより注目される予感がしています。本記事では、超初心者にもハードルが低くなるよう、MicrosoftAzureLogicAppsを使ってノンコーディングでAmazonEchoのスキルを開発してみます。実家に帰省しないと会うことができない愛犬の声をいつでも気軽AmazonEchoから聞くことができるスキルを開発しました。

1. 開発するスキル

今回開発するスキルのイメージはこちらです。呼び出されると、愛犬の声を再生するようにします。
image.png

2. 開発の全体像と流れ

手順は、大きく以下の3ステップです。
①AlexaDeveloperConsoleでスキルの作成
②AzureLogicAppsで応答処理の作成
③自作音声ファイルの準備とDropboxでの共有

image.png

①AlexaDeveloperConsoleでスキルを作成

まず、https://developer.amazon.com/ja/にて、スキルを作成しましょう。AmazonEchoスキルの開発に必要な概念は、Amazon Echo (Alexa) のSkillの開発に必要な基本概念を押さえるを参照してください。今回は、「おさんぽ」とよんだら、音声を返すシンプルなスキルなので、インテントをひとつだけ登録します。おさんぽということで"walking"と命名しました。

image.png

②AzureLogicAppsで応答処理の作成

続けて、AzureLogicAppsにて、AlexaSkillConsoleからIntentを受け取り、応答を返すAPIサーバをAzureLogicAppsで作成します。
AlexaからJSONをうけとりJSONをかえすAPIサーバです。

「もっと丁寧にAzureLogicAppsの使いたいを知りたい!」という方は、以下のLINEBotの作成記事を参考にしてください。
ノンコーディングで質問に自動回答するLINE BOTを作ってみよう

AzureLogicAppsで開発するAPIサーバの全体像ですが以下のイメージになります。
image.png

②-1.HTTP要求の受信時のモジュールを作成

まずはAlexaからPOSTでJSONを受け取れるように、「HTTP要求の受信時」のモジュールを用意します。
メソッドをPSOTに設定し、JSONのスキーマを登録しておきます。
また、HTTP POSTのURLは、先程のAlexaDeveloperConsoleでエンドポイントに登録しておきます。
image.png

「HTTP要求の受信時」のモジュールに登録するJSONスキーマ(クリックすると開きます)
request.json
{
    "properties": {
        "request": {
            "properties": {
                "dialogState": {
                    "type": "string"
                },
                "intent": {
                    "properties": {
                        "confirmationStatus": {
                            "type": "string"
                        },
                        "name": {
                            "type": "string"
                        },
                        "slots": {
                            "properties": {
                                "anatanoslotname": {
                                    "properties": {
                                        "confirmationStatus": {
                                            "type": "string"
                                        },
                                        "name": {
                                            "type": "string"
                                        },
                                        "resolutions": {
                                            "properties": {
                                                "resolutionsPerAuthority": {
                                                    "items": {
                                                        "properties": {
                                                            "authority": {
                                                                "type": "string"
                                                            },
                                                            "status": {
                                                                "properties": {
                                                                    "code": {
                                                                        "type": "string"
                                                                    }
                                                                },
                                                                "type": "object"
                                                            },
                                                            "values": {
                                                                "items": {
                                                                    "properties": {
                                                                        "value": {
                                                                            "properties": {
                                                                                "id": {
                                                                                    "type": "string"
                                                                                },
                                                                                "name": {
                                                                                    "type": "string"
                                                                                }
                                                                            },
                                                                            "type": "object"
                                                                        }
                                                                    },
                                                                    "required": [
                                                                        "value"
                                                                    ],
                                                                    "type": "object"
                                                                },
                                                                "type": "array"
                                                            }
                                                        },
                                                        "required": [
                                                            "authority",
                                                            "status",
                                                            "values"
                                                        ],
                                                        "type": "object"
                                                    },
                                                    "type": "array"
                                                }
                                            },
                                            "type": "object"
                                        },
                                        "value": {
                                            "type": "string"
                                        }
                                    },
                                    "type": "object"
                                }
                            },
                            "type": "object"
                        }
                    },
                    "type": "object"
                },
                "locale": {
                    "type": "string"
                },
                "requestId": {
                    "type": "string"
                },
                "timestamp": {
                    "type": "string"
                },
                "type": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "version": {
            "type": "string"
        }
    },
    "type": "object"
}

②-2.スキル起動時(IntentがLaunchRequestの際)の応答処理を作成

次に、スキル起動時(IntentがLaunchRequestの際)の応答処理を作成していきます。
Alexaから受信するJSONの中のtypeスキーマにLaunchRequestが含まれるので、それがあるかどうか条件式で判別しましょう。
Trueの場合の応答処理を応答モジュールで用意します。

image.png

応答用のJSON(クリックすると開きます)
response1.json
{
  "response": {
    "outputSpeech": {
      "ssml": "<speak><prosody pitch='x-high'>ごんただよ!</prosody></speak>",
      "type": "SSML"
    },
    "reprompt": {
      "outputSpeech": {
        "ssml": "<speak><prosody pitch='x-high'>なにしてあそぶ?</prosody></speak>",
        "type": "SSML"
      }
    },
    "shouldEndSession": "False"
  },
  "version": "1.0"
}

②-3.Intentごとの応答処理を作成

同様に、起動時以外のIntentごとの応答処理を作っていきます。
最小のnameというスキーマにwalkingという値が入って送られてくるので、条件式を用意して、応答処理を作ります。

image.png

応答用のJSON(クリックすると開きます)
response2.json
{
  "response": {
    "outputSpeech": {
      "ssml": "<speak><audio src='https://dl.dropboxusercontent.com/s/あなたの音声ファイルのURL/あなたの音声ファイル.mp3' /></speak>",
      "type": "SSML"
    },
    "reprompt": {
      "outputSpeech": {
        "ssml": "<speak><prosody pitch='x-high'>ほかになにしてあそぶ?</prosody></speak>",
        "type": "SSML"
      }
    },
    "shouldEndSession": "False"
  },
  "version": "1.0"
}

③自作音声ファイルの準備とDropboxでの共有

それでは、AmazonEchoのスキルで使う音声ファイルを用意しましょう。今回はiPhoneで再生した筆者の愛犬のなき声を利用します。

③-1.AmazonEchoで利用可能な形式へ「FFmpeg」を用いて変換

利用可能な形式が限られているため、音声ファイルを変換します。
 - 90秒以内である
 - 特定のビットレート・周波数にフォーマットされている
 - 個人情報や機密情報を含まない

今回は、「FFmpeg」という無料ソフトウェアで対応する形式に変換しました。
参考 AlexaスキルでMP3ファイルを流そう!効果音を入れてワンランクアップのスキル開発

$ ffmpeg -y -i before.mp3 -ar 16000 -ab 48k -codec:a libmp3lame -ac 1 after.mp3

③-2.dropboxでMP3ファイルを共有し、URLを作成する

次に、完成した音声ファイル(MP3ファイル)をオンライン上に共有します。今回は無料で利用可能なDropboxに保存します。
ファイルをアップロードし、共有を行うと、以下のような共有URLが取得できます。

https://www.dropbox.com/s/[取得したURL]?dl=0

しかしこのままではAmazonEchoのスキル上で再生できないので、以下のように少しURLを編集します。このURLを先程のAzureLogicAppsの中のSSML文の中に入れてあげると、Dropboxの音声ファイルをAmazonEchoのスキル上で再生することができるようになります。

https://dl.dropboxusercontent.com/s/[取得したURL]

公式のサウンドライブラリを使う / 音声ファイルを用意できない方へ

今回、自分で用意できない場合は、以下の公式のサウンドライブラリから音源を使うことも可能です。
サウンドライブラリ - Animal Sounds(動物の声)

<speak>
    これはアレクサの通常音声です。音響効果「クマのうなり声(1)」を再生します。
    <audio src='soundbank://soundlibrary/animals/amzn_sfx_bear_groan_roar_01'/>
</speak>

3. まとめ

今回はAzureLogicAppsを使ってAmazonEchoのスキルを作ってみました。一般的にはAWSのLambdaを使った開発が多いですが、JSONの受け渡しができるAPIサーバを用意できれば簡単にAmazonEchoのスキルを開発することができます。ぜひみなさんも作ってみてくださいね!

AzureLogicAppsはオフィス系のモジュール(JiraやSalesforceなど)が多いので、オフィスでのスマートスピーカーアプリ開発にもぴったりです。

image.png

6
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4