Amazon Echoにアイカツナビのココちゃんを召喚した

年末にAmazon Echoシリーズがセールやってたので買ってしまいました。

自分が買ったのはEcho Dot。3420円なり。

https://www.amazon.co.jp/dp/B0792PG3S9

正直スマートスピーカーってどうなん?ほんとに生活便利になるん?という疑問は今でもあります。ストアにあるAlexaスキルを見ても正直ピンとくるものがないし・・・

www.amazon.co.jp

でもまぁせっかくなのでカスタムスキルを作ることにしました。なにかHelloWorld的なものを。

ところで2018年最後のアイカツフレンズ!38話見ました?

www.youtube.com

総集編感はありましたが、なんとアイカツナビのココちゃんが最後に歌ってくれるサプライズ!(途中で切られたけど・・・というか歌ってる途中に会話被せるなよ・・・)

ココちゃんはAIなのでAlexaの題材としてはぴったりですね。

お題

  • 「ハロー、ココちゃん」で「ココだよ!」と返す(当然ココちゃんの声で)
  • 「ココちゃん、歌って」で「いっしょにA・I・K・A・T・S・U!」を最後まで歌わせてあげる

www.youtube.com

俄然やる気出てきたぞ!

Alexaスキル開発学習方法

developer.amazon.com

公式に素晴らしいチュートリアルがあるので、これを一通りやるだけで基本的な開発は学べます。他のブログ記事なんかは一切見なくて大丈夫です。

ただ前提として

  • Node.jsでの開発経験
  • AWS S3、Lambdaの知識

はなんとなくでもあったほうが良いです。

事前準備

  • ココちゃん音源
  • AWSアカウント

対話モデル

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "アイカツナビ",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "SimpleReplyIntent",
                    "slots": [],
                    "samples": [
                        "ハローココちゃん",
                        "返事して"
                    ]
                },
                {
                    "name": "AMAZON.PauseIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ResumeIntent",
                    "samples": []
                },
                {
                    "name": "SingIntent",
                    "slots": [],
                    "samples": [
                        "歌ってココちゃん",
                        "ココちゃん歌って",
                        "歌って"
                    ]
                }
            ],
            "types": []
        }
    }
}

Alexa Developer Consoleがとてもわかり易いので、チュートリアル一通りやったらボタンポチポチしてさくっとできます。

Lambda用関数

github.com

こいつをzipで固めてLambdaにUploadします。

SimpleReplyIntent

「ハロー、ココちゃん」に対する挙動を書きます。

const SimpleReplyIntentHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (
      request.type === "IntentRequest" &&
      request.intent.name === "SimpleReplyIntent"
    );
  },
  handle(handlerInput) {
    const cocodayo = `<audio src='${constants.voiceData.cocodayo}'/>`;
    return handlerInput.responseBuilder.speak(cocodayo).getResponse();
  }
};

Alexaデフォルトの音声ではなく、ココちゃんの「ココだよ!」の声(mp3)を指定します。mp3ファイルは事前にS3にアップロードしておきます。

カスタム音声について

音声合成マークアップ言語(SSML: Speech-Synthesis-Markup-Language)を用いることで、Alexaが生成する音声に追加の制御ができます。 今回は<audio>タグでココちゃんの声を指定しています。 詳しくはこちら。

developer.amazon.com

ココに注目!

音声ファイルは240秒以内でなければなりません。

ビットレートは48 kbpsでなければなりません。

サンプルレートは22050Hz、24000Hz、16000Hzのいずれかです。

結構制限厳しいんです。どこかの動画から抜き出したような音声ファイルだとまず引っかかります。 ffmpeg等のツールで変換してあげましょう。それに関してもドキュメントがあります。

developer.amazon.com

実機で試すと異様にココちゃんの声が遠くに聞こえたのでボリュームも調整してみました。

$ ffmpeg -i ココだよ.mp3 -ac 2 -codec:a libmp3lame -b:a 48k -af volume=20dB -ar 16000 after.mp3

SingIntent

歌わせます。

const SingIntentHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (
      request.type === "IntentRequest" && request.intent.name === "SingIntent"
    );
  },
  handle(handlerInput) {
    return controller.play(handlerInput);
  }
};
(略)
const controller = {
  play(handlerInput, offset = 0) {
    const { responseBuilder } = handlerInput;
    const song = constants.audioData[0];
    responseBuilder
      .withShouldEndSession(true)
      .addAudioPlayerPlayDirective(
        "REPLACE_ALL",
        song.url,
        song.title,
        offset,
        null
      );
    return responseBuilder.getResponse();
  }
};

SimpleReplyIntentと同様、音源を用意するわけですが前述の制限もあり音質も悪いのでAudio Player インターフェースを利用します。

developer.amazon.com

Audio Playerインターフェースを利用するにはAlexa Developer Consoleの「インターフェース」メニューから、「Audio Player」をONにします。

f:id:romiogaku:20181231001132p:plain

追加すると「AMAZON.PauseIntent」と「AMAZON.ResumeIntent」の実装が必須になるため、音楽停止時・再開時の挙動をLambdaに追加で実装します。

// 停止
const PauseIntentHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (
      request.type === "IntentRequest" &&
      (request.intent.name === "AMAZON.CancelIntent" ||
        request.intent.name === "AMAZON.StopIntent" ||
        request.intent.name === "AMAZON.PauseIntent")
    );
  },
  handle(handlerInput) {
    return controller.stop(handlerInput);
  }
};

// 再開
const ResumeIntentHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return (
      request.type === "IntentRequest" &&
      request.intent.name === "AMAZON.ResumeIntent"
    );
  },
  handle(handlerInput) {
    const AudioPlayer = handlerInput.requestEnvelope.context.AudioPlayer;
    const offset = AudioPlayer.offsetInMilliseconds;
    return controller.play(handlerInput, offset);
  }
};

今回は一曲流し切りですが、曲をループさせたり、複数の曲を用意してシャッフルしたりといろいろできるみたいです。

完成!

www.youtube.com

www.youtube.com

う〜ん、このキモオタの声が邪魔ですね。誰だよ。 でもちゃんと反応してくれてます。ココ宮先輩やさしい・・・

最後に

ウェイクワードに「Alexa」と言ってしまっているので、しょせんはこいつはアレクサなんです。ココちゃんじゃないんです。 なんとか「ハローココちゃん」で起動してみたいです。

あとココちゃんって公式的に「koko」なんだろうか。それとも「coco」? →cocoだった。

http://www.aikatsu.net/character/coco.html