#0. はじめに
2018年7月よりProgateやAidemyでプログラミング(とくにPython)を勉強しています。
いつかAmazonEchoのスキルを作ってみたいと思っていたので、
新しく我が家にやってきたEchoSpotと昨年購入したEchoDot2台でのEcho同士が対話するスキルを開発しました。
今回は題材として、お笑いコンビ「ジャルジャル」さんの「国名分けっこ」ゲームをやってみました。
#1. デモ動画
早速ですが、完成したデモ動画がこちらになります。
Amazon Echo2台にジャルジャルの国名分けっこゲームをやらせてみた #python #クリスマス制作 #メリクリ🎄 pic.twitter.com/eqtUtGAhYf
— さい (@saisan78) 2018年12月24日
#2. どうして二台のAmazonEchoで対話?
- 我が家のEchoが二台に増えたから
- Gizmodeの記事「Google HomeとAmazon Echoで2匹のピカチュウの会話を再現した人物が登場、海外メディアも取り上げる」を見て、似たようなことをやってみたかったから
- Qiitaの記事「ジャルジャルの「国名分けっこ」を実装してみた」を拝見して、AmazonEchoにやらせてみたい!と思ったから
- 自分のアウトプットとしてなにか作りたかったから
#3. 国名分けっこゲームとは
12月2日に開催さえた「M-1グランプリ2018」の決勝でジャルジャルが1本目に披露したネタです。
くわしくはYoutubeをご参照ください。
https://www.youtube.com/watch?v=b1J39WQFvSs
#4. 実装の全体像
今回は二台のAmazonEchoを使って、以下のように実装をしました。
ユーザが福徳さん役のスキルを呼び出すと、福徳さん役のスキルが後藤さん役のスキルを呼び出し、
二台のAmazonEchoがネタのように「国名わけっこ」ゲームを開始します。
#5. 苦労&工夫したところ
###Echoから相方Echoのスキルを呼び出す
デモ動画では、福徳さん役のEchoSpotがが、EchoDotから後藤さん役のスキルをよびだしていますよね。
呼び出し方が「エコー、ごとうをひらいて」になっていることにお気づきでしょうか?
「アレクサ」だとEchoSpot自身も呼び出してしまうため、相方の本体の呼び方(ウェイクワード)を変更しました。
【参考】ウェイクワードを変更する
さらに、セリフの中にSSMLの中に休止時間を設けることで、相方のEchoに認識してもらいやすくしました。
<speak><voice name='Takumi'>くにめいわけっこをはじめるぜ!エコー<break time='0.3s'/>後藤をひらいて</voice></speak>
###Echoの発話を相方Echoに認識してもらう
福徳さん役のEchoが話す音声を、後藤さん役のEchoが正確にに認識できないという課題がありました。たとえば、オーストラリアの**「オースト」が「ゴースト」と認識されたり、アルゼンチンの「アルゼン」は「ある前」**と認識されてしまいました。そこで、以下のように認識を調整しました。
- 原作に出題される国名と分け方にのっとりAmazonのIntentを網羅的に作成(アルゼンチン用に、"アル"と"アルゼン"のIntentを作成するなど、全パターンのIntentを作成しました。)
- Echoにどう認識されるか、実際にテストした上で、発話例に登録(アルゼンは"ある前"などと認識されることがテストでわかるため登録しました。)
###SSMLを編集してキャラクターづくり
2人の異なるキャラクターを演出するために、Amazon公式の音声合成マークアップ言語(SSML)のリファレンスを参考にしました。男性の声[Takumi]を利用し、後藤さんのスキルのほうは、[x-high]をいれることで、やや高い声に設定しています。
<speak><voice name='Takumi'><prosody pitch='x-high'>ここに話したいメッセージをいれよう!</prosody></voice></speak>
SSMLのテストは、ポータル内のテストツールが便利でした。
https://developer.amazon.com/ja/
#5. ソースコード(国名ワケっこの後藤さんスキル)
本スキルはすべて、Python(Flask)で作成し、Herokuにデプロイしています。以下の記事を参考にさせていただきました!
ソースコード ※初心者向けにシンプルに書いています。(クリックすると開きます)
from flask import Flask,request,abort,jsonify
import json
import os
app = Flask(__name__)
@app.route("/post_request", methods=['POST'])
def post_callback():
data = request.json
message = ""
endflag = False
print(json.dumps(data, ensure_ascii=False))
#インテントを判別する
try:
type = data["request"]["type"]
except KeyError:
type=""
try:
intent = data["request"]["intent"]["name"]
except KeyError:
intent=""
#スキル起動時の場合のメッセージを記載する
if type == "LaunchRequest":
message = "よし、はじめよう!"
#ここから下にインテントごとの処理を記載する
if intent == "input_any":
try:
message = data["request"]["intent"]["slots"]["any"]["value"] + "ってしらんわ"
except KeyError:
print("KeyError")
elif intent == "aru":
message = "ぜんちん"
elif intent == "aruzen":
message = "ちん"
elif intent == "in":
message = "どねしあ"
elif intent == "indo":
message = "ネシア"
elif intent == "ita":
message = "リア"
elif intent == "ame":
message = "リカ"
elif intent == "kana":
message = "だ"
elif intent == "ousuto":
message = "らりあ"
else:
message = "わからんわ"
reply_body = {
"version":"1.0",
"response":{
"outputSpeech":{
"ssml": "<speak><voice name='Takumi'><prosody pitch='x-high'>" + message + "</prosody></voice></speak>",
"type": "SSML"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak><voice name='Takumi'><prosody pitch='x-high'>つづけて</prosody></voice></speak>"
}
},
"shouldEndSession": endflag
}
}
return jsonify(reply_body)
@app.route("/")
def hello_world():
return "Hello world!!" #デバック用
if __name__ == "__main__":
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
#6. 最後に
簡単ですが、二台のEchoで2つのスキルを連携を実装することができました!
本スキルは一台ずつでも遊ぶことが可能なようにつくっています。(今の所リリースする予定はございません。)
今回は本当にEcho(後藤さんのスキル)が音声認識をして対話しているのですが、
外のノイズ音の影響をうけるので、サーバ間で連携したほうが安心だと思います。笑