Alexa-SDK Ver2(その8) AudioPlayer
1 はじめに
AudioPlayerの利用方法については、既に、ここDevelopers.IOでも紹介されています。
[Alexaスキル] AudioPlayerでハローワールド
[Alexaスキル] AudioPlayerスキルのセッションとイベント
AudioPlayerの再生キューの活用
しかし、上記の記事のサンプルコードは、当時のAlexa SDK V1で書かれています。そこで、本記事では、内容はかなりの部分被りますが、サンプルコードをAlexa SDK V2に変更して書かせていただきました。
なお、Alexa SDK V2については、色々とまとめてきましたので、その流れに乗せ(その8)とさせて頂きました。
[日本語Alexa] Alexa SDK for Node.js Ver2入門(その1)はじめの一歩
[日本語Alexa] Alexa SDK for Node.js Ver2入門(その2)ハンドラの登録
[日本語Alexa] Alexa SDK for Node.js Ver2入門(その3)レスポンスの作成
[日本語Alexa] Alexa-SDK Ver2(その4)スキル属性
[日本語Alexa] Alexa-SDK Ver2(その5)ダイアログモード
[日本語Alexa] Alexa-SDK Ver2(その6) 所在地情報
[日本語Alexa] Alexa-SDK Ver2(その7) ディスプレイ表示
2 AudioPlayerの有効化
AudioPlayerを使用するには、スキルの作成持に、開発者コンソールのインターフェースでAudioPlayerをONにする必要があります。
AudioPlayerをONにすると、デフォルトで追加されるインテントに AMAZON.PauseIntent(一時停止) と AMAZON.ResumeIntent(再開) が追加されます。
3 オーディオ再生
オーディオ再生は、ResponseBuilderのaddAudioPlayerPlayDirectiveを使用します。
PlayerIntentを定義して、sample.mp3を再生する簡単なサンプルは、以下のようになります。
「音楽をかけて」と話しかけると、PlayIntentが呼ばれます。
PlayIntentを処理するハンドラの例です。https://exsample.com/sample.mp3を再生するように指定しています。 なお、ResponseBuilderに、speakを指定すると、再生の直前に発話することも可能です。
const PlayIntentHandler = { canHandle(handlerInput) { const request = handlerInput.requestEnvelope.request; return (request.type === 'IntentRequest' && request.intent.name === 'PlayIntent'); }, async handle(handlerInput) { const url = "https://exsample.com/sample.mp3"; const token = "sample"; return handlerInput.responseBuilder .addAudioPlayerPlayDirective('REPLACE_ALL', url, token, 0, null) //.speak('サンプルを再生します。') .getResponse(); } };
4 addAudioPlayerPlayDirective
ここで、addAudioPlayerPlayDirectiveの定義は以下のとおりです。
addAudioPlayerPlayDirective ( playBehavior: interfaces.audioplayer.PlayBehavior, url: string, token: string, offsetInMilliseconds: number, expectedPreviousToken?: string, audioItemMetadata? : AudioItemMetadata): this;
(1) playBehavior: interfaces.audioplayer.PlayBehavior
指定したオーディオの再生方法を指定します。
- REPLACE_ALL: 再生中のストリーム及び、キューを置き換えて、すぐに再生を開始します。
- ENQUEUE: 現在のキューの最後に追加します。再生中のストリームには影響しません。
- REPLACE_ENQUEUED: キューを置き換えます。再生中のストリームには影響しません。
(2) url: string
オーディオコンテンツのURLを指定します。
使用可能なファイルの形式はAAC/MP4、MP3、HLSなどでビットレートは、16kbps~384kbpsです。HTTPSは必須で、ドメインには有効なSSL証明書が必要です。(オレオレ証明は使用できません)
(3) token: string
オーディオストリームを識別するためのトークンで、1024文字以内の文字列が指定できます。(自由に設定できます)
(4) offsetInMilliseconds: number
再生を開始するタイムスタンプです。最初から再生する場合は0を指定します。
(5) expectedPreviousToken?: string
前のストリームを指定します。playBehavior が ENQUEUE の場合に必須の指定となります。
(6) audioItemMetadata? : AudioItemMetadata
オーディオに関連するメタデータを指定します。Echo Show と Echo Spot で表示されます。(Alexaアプリには表示されません)
5 Amazon.PauseIntent「中断して」
AudioPlayerインターフェースで、実装が必須となっているAmazon.PauseIntentの実装例は以下のとおりです。
const PauseIntentHandler = { canHandle(handlerInput) { const request = handlerInput.requestEnvelope.request; return (request.type === 'IntentRequest' && request.intent.name === 'AMAZON.PauseIntent'); }, async handle(handlerInput) { return handlerInput.responseBuilder //.speak('サンプルを中断します。') .getResponse(); } };
ユーザーによる「中断して」などのリクエストに答えるものですが、ここでは、空のレスポンスを返しても、再生中のオーディオは停止します。なお、Amazon.PauseIntentは、通常のインテントと同じなので、speakで発話させる事も可能です。
6 Amazon.ResumeIntent「再開して」
実装が必須となっている、もう一つのインテントであるAmazon.ResumeIntentの実装例は以下のとおりです。
const ResumeIntentHandler = { canHandle(handlerInput) { const request = handlerInput.requestEnvelope.request; return (request.type === 'IntentRequest' && request.intent.name === 'AMAZON.ResumeIntent'); }, async handle(handlerInput) { const url = "https://exsample.com/sample.mp3"; const AudioPlayer = handlerInput.requestEnvelope.context.AudioPlayer; const token = AudioPlayer.token; const offset = AudioPlayer.offsetInMilliseconds; return handlerInput.responseBuilder .addAudioPlayerPlayDirective('REPLACE_ALL', url, token, offset, null) //.speak('サンプルを再開します。') .getResponse(); } };
オーディオ再生を開始した時と同じで、ResponseBuilderのaddAudioPlayerPlayDirectiveを使用していますが、今度は、再開なので、中断している位置(オフセット)からのスタートとします。
オフセット(及び、トークン)については、Alexaからのコンテキストに含まれていますので、これを利用しています。(urlについては、Contentに含まれませんので、スキル側で記憶する仕組みが必要です)
{ "context": { "AudioPlayer": { "offsetInMilliseconds": 3578, "token": "sample", "playerActivity": "STOPPED" }, ・・・略・・・ }, "request": { "type": "IntentRequest", "intent": { "name": "AMAZON.ResumeIntent", ・・・略・・・ } }
7 AudioPlayerのイベント
AudioPlayerを使用すると、オーディオの「再生開始」や「終了」又、「もうすぐ終了する」などのリクエストがスキルに送られます。 特に必要がなければ無視しても良いのですが、スキルに実装がないとLambdaでエラーとなってしまいますので、下記のように処理しておくことをお勧めします。
こちらのイベントで送られてきているリクエストのタイプはIntentRequestではなく、また、Alexaへの指示ができません。そのため、誤って、ResponseBuilderにspeakなどを追加すると、エラーとなりますので注意が必要です。
const PlaybackHandler = { canHandle(h) { const type = h.requestEnvelope.request.type; return (type == 'AudioPlayer.PlaybackStarted' || // 再生開始 type == 'AudioPlayer.PlaybackFinished' || // 再生終了 type == 'AudioPlayer.PlaybackStopped' || // 再生停止 type == 'AudioPlayer.PlaybackNearlyFinished' || // もうすぐ再生終了 type == 'AudioPlayer.PlaybackFailed'); // 再生失敗 }, async handle(handlerInput) { return handlerInput.responseBuilder .getResponse(); } };
8 テストできない
オーディオ再生は、開発者コンソールのテストで確認することはできません。
デバイスのログを確認すると、AudioPlayer.Playディレクティブが、端末側に返っていることまでは、確認できますが、未対応である旨のポップアップと共にスキルは終了してしまいます。
9 最後に
今回は、Alexa SDK V2による、AudioPlayerインターフェースを使用したスキルの作成についてまとめてみました。
AudioPlayerインターフェースは、完全に、ResponseBuilderにラップされているため、非常に簡単に利用可能です。次回は、AudioPlayerのイベントを処理し、オーディオの連続再生について扱いたいと思います。
10 参考リンク
AudioPlayer の概要
[Alexaスキル] AudioPlayerでハローワールド
[Alexaスキル] AudioPlayerスキルのセッションとイベント
AudioPlayerの再生キューの活用
AudioPlayerインターフェースのリファレンス
AudioPlayer インターフェース(v1.0)