Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@tknm02

Alexaをダイヤルアップ接続させるジョークアプリ作ってみた

経緯と目的

仕事中調べ物をしていたら、明日のLambda枠が空いていたので勢いで登録してしまいました。
最近echo plus手に入れて、alexa skillトレーニングを勉強したので、復讐がてら簡単に作って投稿してみます。

とりあえず目的は以下

  1. alexa skill kitを使って何か作る
  2. 今日中(残り4時間)で作って記事を書く
  3. とりあえず動かすのを目的に
  4. 色々書いてみる
  5. 楽しむ

まだ勉強し始めたばかりなので、色々間違っていたり、ダサいコーディングもありますが寛大な目で見てください

時間記録

20:00 帰宅、PC起動、qiita執筆開始
20:10 食事 200円引きの寿司
20:30 食事終了、skill作成、lambda作成、S3作成
21:10 youtubeで息抜き
22:00 テストしながらコーディング
23:00 動画撮影、qiita編集
23:30 投稿

何を作るか

alexa skillには色々な人がskillを作成して公開しています。
私も部屋のライトをphillipsのhueに変えたり、amazon music unlimitedに入って
気分によって音楽を変えたりニュース聞いたりレシピ聞いたり毎日が楽しくてしょうがありません。

今回は流石に技術も時間も無いので、どうせならハイテクなalexaにローテクっぽい事をさせてみようと思います。

というわけで、alexa をダイヤルアップ接続させるジョークアプリを作ってみます!
あくまでジョークアプリなので、一切接続しませんし出来ません。
slとかfortuneコマンドとか好きなんです。

スキル開発

スキル概要を入力
今回は対話モデルですが、そこまで対話させません。
ステートも使わない予定です。
ここで入力した、alexa 【呼び出し名】 を開いて
と言うと、alexaが開きます。
Audio Playerにチェック付けていますが、多分必要ありません。

84741863a47a1fc44e15efd5bdca47ab.png

インテント

インテントはとりあえずこれのみ
シンプル!
インテントとは、イベント名みたいなものです。
ここで設定したインテント毎にlambda上で細かい処理を書けます。


{
  "intents": [
    {
      "intent": "StartDialUp" //回線が繋げる時のインテント
    },
    {
      "intent": "AMAZON.HelpIntent" //ヘルプインテント
    }
  ]
}

サンプル発話

サンプル発話には以下を設定
ここに入力した【インテント名 発話】を話しかけてLambdaで処理を行います

StartDialUp 接続 を 開始して
StartDialUp ダイヤルアップ回線 に 繋いで
StartDialUp 回線 を 繋いで
StartDialUp はい
StartDialUp 繋げて

S3にファイルアップロード

  1. クリエイティブ・コモンズライセンスのダイヤルアップ接続音を探してDL
  2. ビットレートを48kbpsにしなくてはならないため ffmpeg をインストールして変換
  3. ffmpeg -i foo.mp3 -ac 2 -codec:a libmp3lame -b:a 48k -ar 16000 bar.mp3
  4. S3にバケットを作成し、ダイヤルアップ接続の音をアップロード
  5. 公開に設定するのを忘れない

Lambda

  1. AWSにログインしてLambdaを作成
  2. 設計図からalexa-skill-kit-sdk-factskillを選択
  3. connectToDialup 関数を作成

6fa6d6faf5830d99a57ba625d72da51e.png

4.左から Alexa Skills Kitを選択し保存

ff68fe06325a1346a46636251e19e1b8.png

5.connectToDialupを選択し、ソースコードにデフォルトでalexa-sdkが読み込まれたindex.jsがあるのでそれを編集

先週弄ったときとデフォルトが変わっているので困惑…
多言語用の変数があるようなので、よく分からないけど試しに追加。
結局殆ど使っていませんが、多言語対応するさいはこちらで各言語入れればいいので楽ですね。

index.js
    'ja': {
        translation: {
            FACTS: [
                'ダイヤルアップ回線に接続したいですか?',
            ],
            SKILL_NAME: 'ダイヤルアップ回線',
            GET_FACT_MESSAGE: 'ダイヤルアップ回線に接続しますか?',
            HELP_MESSAGE: 'ダイヤルアップ回線を開いてと言ってください',
            HELP_REPROMPT: 'ダイヤルアップ回線を開いてと言ってください',
            STOP_MESSAGE: 'もっと早い回線が見つかりましたのでそちらに切り替えます',
        },
    },

6.コードを変更

今回はそこまで変えていません。
AMAZON.HelpIntent の中で、先程の各言語毎のFACTSとかを読み込んでいたのですが今回は削除しました。

index.js
const handlers = {
    'LaunchRequest': function () {
        this.emit('GetFact');
    },
    'GetNewFactIntent': function () {
        this.emit('GetFact');
    },
    'GetFact': function () {
        // Get a random space fact from the space facts list
        // Use this.t() to get corresponding language data

        const speechOutput = this.t('GET_FACT_MESSAGE');
        this.emit(':ask', speechOutput);
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = this.t('HELP_MESSAGE');
        const reprompt = this.t('HELP_MESSAGE');
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'StartDialUp': function () {
        let speechOut = '回線につなげます';
        speechOut += "<break time ='1s' />";
        speechOut += "<audio src='https://s3-ap-northeast-1.amazonaws.com/hoge/hogehoge.mp3' />";
        speechOut += "<break time ='1s' />";

        // 遅延しているような声
        let complete = "ダ,イ,ヤ,ル,アッ,プ,回,線,に,つ,な,が,り,ま,し,た";
        let completes = complete.split(',');
                completes.forEach(function(val, key){
            if (Math.floor( Math.random() * 6 ) % 3 === 0) {
                speechOut += "<break time ='1s' />";
            }
            speechOut += val;
            if (Math.floor( Math.random() * 6 ) % 3 === 0) {
                speechOut += "ーー";
            }
        });

        this.emit(':tell', speechOut);
    },
};
    'StartDialUp': function () {
        let speechOut = '回線につなげます';
        speechOut += "<break time ='1s' />";
        speechOut += "<audio src='https://s3-ap-northeast-1.amazonaws.com/hoge/hogehoge.mp3' />";
        speechOut += "<break time ='1s' />";

        // 遅延しているような声
        let complete = "ダ,イ,ヤ,ル,アッ,プ,回,線,に,つ,な,が,り,ま,し,た";
        let completes = complete.split(',');
                completes.forEach(function(val, key){
            if (Math.floor( Math.random() * 6 ) % 3 === 0) {
                speechOut += "<break time ='1s' />";
            }
            speechOut += val;
            if (Math.floor( Math.random() * 6 ) % 3 === 0) {
                speechOut += "ーー";
            }
        });

音声を流すのはここの処理になります。
SSMLタグについては、こちらを参考にさせて頂きました。

<audio src='https://s3-ap-northeast-1.amazonaws.com/hoge/hogehoge.mp3' />

このように記述することで、音声ファイルを流せますが、以下ご注意ください。

使用するMP3にはいくつかの条件があります。
 ・ インターネット上でホスティングされた HTTPSエンドポイントで提供されていること。
 ・ SSL証明書がオレオレ証明書ではなくAmazonの基準を満たす証明書であること。(公式サイトではAWS S3の使用を提案しています)
 ・ カスタマーの個人情報やその他デリケートな情報を含んでいないこと
 ・ 有効なMP3ファイルであること(MPEG version 2)
 ・ 90秒以内であること
 ・ ビットレートが48KB/sであること
 ・ サンプルレートが16,000Hzであること

あと無駄に遅延しているような声を追加しています。
とりあえず動かしてみます。

IMAGE ALT TEXT HERE

動いた!
最後の遅延してるっぽい声微妙でしたね
他にいいやり方あれば色々試してみたいです

まとめ

短時間でも簡単にスキルを作れるalexa skill kitとlambdaは素晴らしい!
こういうジョーク系のアプリって審査通るのかな?

何か面白そうなアイディアがあればまた作ってみます!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What are the problem?