概要
APL for Audioで、発話の長さに合わせてオーディオの再生時間が自動で調整されるという地味に嬉しい機能が追加されました。
これ何が嬉しいのか?実際にやってみましょう。
これまでのAPL for Audioのめんどくさかったところ
APL for Audioの一番わかり安い例として、BGMにあわせてAlexaに発話させるというのがあります。以下のサンプルコードを見てください。
{ "type": "Alexa.Presentation.APLA.RenderDocument", "token": "token", "document": { "type": "APLA", "version": "0.91", "description": "APL for Audioのサンプルです。", "mainTemplate": { "parameters": [ "payload" ], "item": { "type": "Mixer", "items": [ { "type": "Speech", "contentType": "SSML", "content": "<speak><break time=\"2s\"/><voice name=\"Takumi\">はじめまして。僕の名前は ${payload.user.name}。これからお供の動物たちと一緒に鬼ヶ島に鬼を退治に行く途中なんだ。応援してね</voice><break time=\"1s\"/>おしまい。次回をお楽しみに。</speak>" }, { "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1" } ] } } } }
"type": "Mixer"
を使うと配下のアイテム(speechやaudio)が並列で再生されます。サンプルではitems
に2つの要素が指定してあります。"type":"Speech"
がAlexaの発話、"type":"Audio"
がオーディオファイルの再生です。音楽に乗せてAlexaが話してくれるわけですね。
早速試してみましょう。Alexa開発者コンソールのどのスキルでもいいので、一度開いて、メニューにある「マルチモーダル」をクリックします。
マルチモーダル画面が開いたら、"Create Audio Response"をクリックします。2つボタンがありますが、どちらでもよいです。
APL for Audioのエディタが開きます。
左のメニューで"APLA"が選択されていることを確認して・・・
サンプルコードですべて上書きします。
次に、左のメニューから"DATA"をクリックします。
こちらに以下のコードを全部上書きしてください。
{ "user": { "name": "桃太郎" } }
できたら下にある"Preview"ボタンをクリックします。
APLのコードが読み込まれ、波形が表示されているのがわかりますね。再生ボタンを押してみてください。
Alexaの発話と音楽が同時に流れたと思います。が、Alexaの発話が終わっても音楽が延々と流れていますよね?
今回のオーディオファイルはちょうど4分あります。でもAlexaの発話はせいぜい20秒程度です。ちょっとオーディオが長すぎですよね。
これに対応するには以下の2つの方法があります。
- オーディオファイルをAlexaの発話時間に合わせて短くしたものに差し替える
- APL for Audioのフィルタを使ってオーディオの再生時間を制御する
1つ目はオーディオファイルそのものを時間を短くするやり方です。2つ目はAPL for Audioのフィルタ機能を使うやり方です。後者のほうがお手軽なのでやってみましょう。以下のコードで全部上書きしてください。
{ "type": "Alexa.Presentation.APLA.RenderDocument", "token": "token", "document": { "type": "APLA", "version": "0.91", "description": "APL for Audioのサンプルです。", "mainTemplate": { "parameters": [ "payload" ], "item": { "type": "Mixer", "items": [ { "type": "Speech", "contentType": "SSML", "content": "<speak><break time=\"2s\"/><voice name=\"Takumi\">はじめまして。僕の名前は ${payload.user.name}。これからお供の動物たちと一緒に鬼ヶ島に鬼を退治に行く途中なんだ。応援してね</voice><break time=\"1s\"/>おしまい。次回をお楽しみに。</speak>" }, { "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1", "filter": [ { "type": "Trim", "end": 20000 }, { "type": "FadeOut", "duration": 3000 } ] } ] } } } }
上書きしたら、左下の再読み込みボタンをクリックします。
そして再生してみます。
変更したのは以下のところです。
{ "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1", // 最後にカンマを追加 "filter": [ // 以下を追加 { "type": "Trim", "end": 20000 }, { "type": "FadeOut", "duration": 3000 } ] // ここまで }
"source"で指定されているオーディオファイルのURLの下にfilterというのが追加されています。あと、URL行の末尾にカンマが追加されていることにも注意してください。
filterを使うとオーディオの再生を調整できます。設定しているのは以下です。
- "Trim"を使って、オーディオファイルの再生時間を20秒に指定
- "FadeOut"を使って、オーディオファイルの最後3秒間でフェードアウトさせる
つまり、発話の時間にあわせて再生時間を調整しているわけですね。オーディオファイルそのものを短くするよりはぜんぜん楽ですよね。
でもちょっと待って下さい。
- もし発話の長さが変わったらどうしましょう?
- さらに、発話部分がユーザから受け取った発話に応じて動的に変わったらどうすればよいでしょう?
再生時間を事前に制御するのはとても難しくなります。
そこで今回新しく追加されたのが"Duration"です。
Durationプロパティ
DurationプロパティはMixerの子コンポーネントに対して指定します。Durationプロパティには"auto"と"trimToParent"が指定でき、"auto"がデフォルトです。"auto"は何も変わりませんが、重要なのは"trimToParent"です。これが設定されたコンポーネントは、Mixerの子コンポーネントの中で最も再生時間が長いコンポーネントにあわせて、再生時間が自動で調整されます。
ちょっと説明がわかりにくいかもしれません。やってみましょう。以下のコードで上書きします。
{ "type": "Alexa.Presentation.APLA.RenderDocument", "token": "token", "document": { "type": "APLA", "version": "0.91", "description": "APL for Audioのサンプルです。", "mainTemplate": { "parameters": [ "payload" ], "item": { "type": "Mixer", "items": [ { "type": "Speech", "contentType": "SSML", "content": "<speak><break time=\"2s\"/><voice name=\"Takumi\">はじめまして。僕の名前は ${payload.user.name}。これからお供の動物たちと一緒に鬼ヶ島に鬼を退治に行く途中なんだ。応援してね</voice><break time=\"1s\"/>おしまい。次回をお楽しみに。</speak>" }, { "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1", "duration": "trimToParent" } ] } } } }
変更したのはAudioコンポーネントにDuration: "trimToParent"
を追加しただけです。
発話が終わるのと同時に再生が止まりましたね!
今回、Mixerで指定されているコンポーネントは2つです。最も再生時間が長いのはオーディオの方ですが、こちら側にDuration: "trimToParent"
が設定されるので、これ以外で最も長いのは発話の方になります。つまり、発話の時間に合わせてオーディオの再生時間が自動で調節されるというわけです。
発話内容が動的に変化したとしても、オーディオはそれにあわせて再生時間が調整されるのでとても便利ですね!
ただ、ちょっといきなり切られる感じになりますね・・・ということで、filterでfadeOutを指定してみました。
{ "type": "Alexa.Presentation.APLA.RenderDocument", "token": "token", "document": { "type": "APLA", "version": "0.91", "description": "APL for Audioのサンプルです。", "mainTemplate": { "parameters": [ "payload" ], "item": { "type": "Mixer", "items": [ { "type": "Speech", "contentType": "SSML", "content": "<speak><break time=\"2s\"/><voice name=\"Takumi\">はじめまして。僕の名前は ${payload.user.name}。これからお供の動物たちと一緒に鬼ヶ島に鬼を退治に行く途中なんだ。応援してね</voice><break time=\"1s\"/>おしまい。次回をお楽しみに。<break time=\"3s\"/></speak>" }, { "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1", "duration": "trimToParent", "filter": [ { "type": "FadeOut", "duration": 3000 } ] } ] } } } }
が、効かないですね・・・発話の方にもSSMLで3秒の空白追加して長くしてみたんですが変わらず。FadeOutフィルターは再生時間の最後n秒をフェードアウトするものなので、trimToParentで再生時間を自動調整する場合はちょっと難しいのかもしれませんね。FadeInの方は動作しますし。ここは今後の改善に期待かも。
2021/02/14 追記
Twitterでできないよー、とつぶやいてみたら、ヒントもらえました。
new APL for Audio's automatic trimToParent feature is very nice, but seems FadeOut filter does not work with it.#alexadevs
— kun432@VFJUG🇯🇵 (@kun432) 2021年2月13日
like this:
— kun432@VFJUG🇯🇵 (@kun432) 2021年2月13日
"duration": "trimToParent",
"filter": [
{
"type": "FadeOut",
"duration": 3000
}
Not sure of your whole code. But @austinvach said a trick need to be done to make it work. Here’s the code he wrote. Basically you have to apply the repeat filter first (to fill up) and THEN apply the fadein or fadeout. https://t.co/wIEYRz7ybG
— GoldZulu (@VoiceTechGuy1) 2021年2月13日
Thanks! very interesting. My test code is very simple. 1 Mixer has 2 child component: 20s speech, and 240s audio with trimToParent and fadeout. I fixed my code to set fadeout to Mixer itself, then works!
— kun432@VFJUG🇯🇵 (@kun432) 2021年2月13日
Mixer with fadeout means fadeout both child component, including speech. In your code break added with same duration of fadeout at the end of speech. Great!
— kun432@VFJUG🇯🇵 (@kun432) 2021年2月13日
こういう感じですね。
{ "type": "Alexa.Presentation.APLA.RenderDocument", "token": "token", "document": { "type": "APLA", "version": "0.91", "description": "APL for Audioのサンプルです。", "mainTemplate": { "parameters": [ "payload" ], "item": { "type": "Mixer", "filter": [ { "type": "FadeOut", "duration": 3000 } ], "items": [ { "type": "Speech", "contentType": "SSML", "content": "<speak><break time=\"2s\"/><voice name=\"Takumi\">はじめまして。僕の名前は ${payload.user.name}。これからお供の動物たちと一緒に鬼ヶ島に鬼を退治に行く途中なんだ。応援してね</voice><break time=\"1s\"/>おしまい。次回をお楽しみに。<break time=\"3s\"/></speak>" }, { "type": "Audio", "description": "Audioでオーディオファイルの再生が可能です。今回のBGMはSHW様(http://shw.in/)のフリー音源を使用させていただいております。", "source": "https://www.dropbox.com/s/fjy0lc35708cbuf/takanoniharuka.mp3?dl=1", "duration": "trimToParent" } ] } } } }
親となるMixerコンポーネント側でFadeOutフィルターを適用すればいいみたいです。ただしその場合は、FadeOutがMixer配下のコンポーネント全体にかかる、つまりSpeechにもかかってしまうので、Speechの最後にFadeOutの長さと同じだけのbreakを追加しておくということですね。なるほど。
まとめ
今回の例では、発話の時間<オーディオの時間でした。逆に、発話の時間>オーディオの時間の場合はどうなるのでしょうか?
というところは次回ご紹介します。