Echo dot で mp3 を再生する(Alexa スキル:python)

Python でも開発できる Alexa スキルですが、音楽(mp3)の再生で検索すると、Node.js の参考サイトが多く出てきてきます。Python で mp3 を再生できるようになるまでに少し苦労しました。結局のところ、Amazon が提供しているサンプルコードが一番わかりやすかったのですが、とにかく mp3 を再生してみたい!という場合に、この記事を参考にしてみてください。
私が試した実環境は、Echo dot(第4世代)と、スマホの Alexa アプリです。この2つの環境で音楽再生ができました。

参考:
AudioPlayer のインターフェースリファレンス
AudioPlayer のサンプル

みなさんPython の勉強進んでいるでしょうか。私は記事にしていないところでも、いろいろと楽しんでいますが、PC 上だけで動かしているとやることが限られてきます。ちょっと調べ...
スポンサーリンク

スキルで MP3 ファイルを再生する!

理解を深めつつ、モチベーションを保つために、とにかく自分の作ったスキルで mp3 を再生してみましょう。前提として、mp3 ファイルへは、ネットワークでアクセスできる必要があります。今回は、Google Drive を使いました。

今回はmp3を再生することだけを目標にしたため、曲が停止できないような乱暴なコードになっています。別のスキルを起動して強制的に止めるなどの処置が必要です。

MP3ファイルの準備

Google Drive に mp3 ファイルを配置し、URL 共有を行います。この時、URL 共有のファイルの ID を控えておきます。今回は、Mp3File1XxXxXxXxX であるとして進めます。

https://drive.google.com/file/d/ と /view?usp=sharing に囲まれた部分を ファイルID としてメモしておきます。

スキル(モデル)の準備

とりあえず、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() という関数があり、これを実装することで停止も可能です。今回は「再生」だけに着目した簡単なコードとなっていますが、次回はもう少し踏み込んだものを作ってみる予定です。