Python でも開発できる Alexa スキルですが、音楽(mp3)の再生で検索すると、Node.js の参考サイトが多く出てきてきます。Python で mp3 を再生できるようになるまでに少し苦労しました。結局のところ、Amazon が提供しているサンプルコードが一番わかりやすかったのですが、とにかく mp3 を再生してみたい!という場合に、この記事を参考にしてみてください。
私が試した実環境は、Echo dot(第4世代)と、スマホの Alexa アプリです。この2つの環境で音楽再生ができました。
参考:
AudioPlayer のインターフェースリファレンス
AudioPlayer のサンプル
スキルで MP3 ファイルを再生する!
理解を深めつつ、モチベーションを保つために、とにかく自分の作ったスキルで mp3 を再生してみましょう。前提として、mp3 ファイルへは、ネットワークでアクセスできる必要があります。今回は、Google Drive を使いました。
MP3ファイルの準備
Google Drive に mp3 ファイルを配置し、URL 共有を行います。この時、URL 共有のファイルの ID を控えておきます。今回は、Mp3File1XxXxXxXxX であるとして進めます。
スキル(モデル)の準備
とりあえず、Google drive 上の MP3 が Alexa 流せることの確認のために、先日作成した「こんにちは」の発話で、「こんにちは!」と返してくれる、「スキルテスト」を利用します。
先日のスキルを開き、「ビルド」>「インターフェース」で、AudioPlayer を ON にします。「インターフェースを保存」をクリックし、「モデルをビルド」をクリックします。
スキル(コード)の準備
AudioPlayer のインターフェースを import します。
1 2 3 | from ask_sdk_model.interfaces.audioplayer import ( PlayDirective, PlayBehavior, AudioItem, Stream, AudioItemMetadata, StopDirective, ClearQueueDirective, ClearBehavior) |
AudioPlayer のサンプル(SingleStream)から、以下の alexa.util.play() を貼り付けます。lambda_function.py 内の各ハンドラクラスの上でいいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | def play(url, offset, text, card_data, response_builder): # type: (str, int, str, Dict, ResponseFactory) -> Response if card_data: response_builder.set_card( StandardCard( title=card_data["title"], text=card_data["text"], image=Image( small_image_url=card_data["small_image_url"], large_image_url=card_data["large_image_url"]) ) ) # Using URL as token as they are all unique response_builder.add_directive( PlayDirective( play_behavior=PlayBehavior.REPLACE_ALL, audio_item=AudioItem( stream=Stream( token=url, url=url, offset_in_milliseconds=offset, expected_previous_token=None), metadata=add_screen_background(card_data) if card_data else None ) ) ).set_should_end_session(True) if text: response_builder.speak(text) return response_builder.response |
HelloWorldIntentHandler クラスの handle() を以下のように変更します。Mp3File1XxXxXxXxX の部分は mp3 の準備でメモした自分の mp3 のファイルID に置き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 | class HelloWorldIntentHandler(AbstractRequestHandler): """Handler for Hello World Intent.""" def can_handle(self, handler_input): # type: (HandlerInput) -> bool return ask_utils.is_intent_name("HelloWorldIntent")(handler_input) def handle(self, handler_input): # type: (HandlerInput) -> Response id = "Mp3File1XxXxXxXxX" # ← ここを準備したファイルIDへ変更 mp3_url = "https://drive.google.com/uc?export=download&id=" + id return play(url=mp3_url, offset=0, text=None, card_data=None, response_builder=handler_input.response_builder) |
シミュレーターでは、MP3は再生されないので注意
Unsupported Directive
AudioPlayer is currently an unsuppored namespace. Check the device log for more information.
スキルシミュレータで動作を確認しようとすると、シミュレータの右下に、上の様なエラーが出てきます。シミュレータでは Audio の再生は行われないようで、実機が必要になります。Alexa 端末を持っていない人は、スマホに Alexa アプリを入れて開発のアカウントでログインすると、開発中の「スキルテスト」が呼び出せます。
最後に
とりあえず「再生」を目指して、スキルを書いたため、曲がストップができなかったりいろいろ問題なコードになっていますが、音楽が再生されてテンションは上がったかなと思います。実機で実行した場合は、別のスキルを呼び出すなどして、ストップさせましょう。
AudioPlayer のサンプルコードを見てみると stop() という関数があり、これを実装することで停止も可能です。今回は「再生」だけに着目した簡単なコードとなっていますが、次回はもう少し踏み込んだものを作ってみる予定です。