atskimura-memo

あまり仕事とは関係なく適当に書きます。開発ネタが多いかもしれません。

Alexaでハリーポッターの呪文を唱えるスキルを作った

f:id:a_kimura:20180109111718j:plain unsplash-logoEster Marie Doysabas

はじめに

1年半ぶりの投稿となってしまいました。
昨年はあまりにアウトプットが少なかったので、いつまで続くかわかりませんが、今年はちょいネタでも書いていこうかと思います。

Google Home miniとAmazon Echo Dotを買ったので最近たまに遊んでいます。
Echo Dotは12月末にやっと来ました。

父「なんか冬休みに作るAlexaスキルのアイデアない?」
娘「呪文唱えるとか?」

というわけで作りました。

ハリーポッターの呪文を唱えると、映画のその呪文発動シーンが(音声で)流れるスキルです。

ルーモスと唱えたら照明が点く、アロハモラと唱えたら玄関の鍵が開くとかモノと絡めたら、もうちょっとおもしろいだろうことはわかりますが、面倒なのでただ音を流すだけです。

著作権も考慮して最初は独自呪文と独自効果音で作りましたが、全く娘にウケなかったため、個人利用ですし、ハリーポッターに変更しました。

作り方

事細かには書かないので、詳しくはドキュメントを見てください。
一度クラスメソッドさんが作っているAlexaスキル開発トレーニングをやると以下の情報だけで作れると思います。

音声ファイルを準備

映画の中の魔法発動シーンをうまいこと切り出します。大変地道な作業です。

なお、作成した音声ファイルはAlexaに適した形式に変換する必要があります。(詳しくは音声合成マークアップ言語(SSML)のリファレンス | Custom Skills

ファイルを作ったらS3にアップロードします。

Alexaスキル

スキル情報

呼び出し名は「ホグワーツ」にしました。「ホグワーツを開いて」で起動します。

インテントスキーマ
{
  "intents": [
    {
      "slots": [
        {
          "name": "MagicSpell",
          "type": "ListOfMagicSpell"
        }
      ],
      "intent": "CastSpellIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}
カスタムスロットタイプ

タイプ: ListOfMagicSpell

アロハモラ
エクスペリアームス
エクスペクト・パトローナム
ウィンガーディアム・レビオーサ
リディキュラス

切り出しが面倒なので、切り出したのはこの5つ。

サンプル発話
CastSpellIntent {MagicSpell}

Lambda関数

"use strict";
const Alexa = require('alexa-sdk');
// ステートの定義
/*const states = {
  CASTSPELLMODE: '_CASTSPELLMODE'
};*/
const spells = {
  "アロハモラ": "Alohomora_BGM.mp3",
  "エクスペリアームス": "Expelliarmus_BGM.mp3",
  "エクスペクトパトローナム": "ExpectoPatronum_BGM.mp3",
  "ウィンガーディアムレビをさ": "WingerdiumLeviosa_BGM.mp3",
  "リディキュラス": "Riddikulus_BGM.mp3",
};
exports.handler = function(event, context, callback) {
  const alexa = Alexa.handler(event, context);
  // alexa.appId = process.env.APP_ID;
  alexa.registerHandlers(handlers);
  alexa.execute();
};
var handlers = {
  'LaunchRequest': function () {
    this.emit('AMAZON.HelpIntent');
  },
  'AMAZON.HelpIntent': function () {
    this.emit(':ask', 'ホグワーツ魔法魔術学校にようこそ!魔法を唱えてみてください。');
  },
  'CastSpellIntent': function() {
    const spell = this.event.request.intent.slots.MagicSpell.value;
    const audio = spells[spell];
    if (audio) {
      const message = '<audio src="https://<S3のバケットのURL>/' + audio + '" />' +
        'すごいですね!大成功です。その調子でもっと練習しましょう!';
      const reprompt = 'もう一度挑戦しましょう!';
      this.emit(':ask', message, reprompt);
    } else {
      this.emit('Unhandled');
    }
  },
  'Unhandled': function () {
    const reprompt = '残念。失敗です。もう一度やってみましょう!';
    const message = '<audio src="<S3のバケットのURL>/Failed.mp3" />' + reprompt;  
    this.emit(':ask', message, reprompt);
  }
};

「ウィンガーディアムレビをさ」となっていますが、この辺がおもしろいところで、「ウィンガーディアム・レビオーサ」と発話するとAlexaさんの音声認識で「ウィンガーディアムレビをさ」とテキスト化されちゃうんですね。なので、仕方なくこうしてみたところ動きました。
Alexaさんは未知の単語を変な風に解釈する率がGoogle Homeより高い気がします。

Failed.mp3 はシェーマス・フィネガン君の魔法失敗シーンから拝借しました。

こんな風に動きます

終わりに

娘は一回は遊んでくれましたが、その後一度も遊んでくれません…
うん。あまりおもしろくないとは思う…