AVS官方文档链结: https://developer.amazon.com/zh/docs/alexa-voice-service/audioplayer.html
下图表示了由AudioPlayer的各组件所驱动的转换变换。方框代表了AudioPlayer状态,箭头代表了状态的迁移方式。
IDLE: AudioPlayer只会在当产品刚开始启动或重开机,且在执行Play指令之前才会处于_idle_状态。
PLAYING: 当你的客户端初始化了某个音频流的播放时,AudioPlayer必须从_idle_状态进入_playing_。
如果你收到了要求客户端执行动作的指令时,例如暂停或停止音频流,但是客户端在缓存流有问题,或播控失败时,AudioPlayer在动作执行时必须转移到合适的状态 (并对AVS发出event)。否则,AudioPlayer必须维持在_playing_状态,直到当前流结束。
此外,当以下情况时,AudioPlayer必须维持在playing状态:
向AVS上报播放进度时
向AVS传送流元数据时
STOPPED:在四种状况下AudioPlayer是必须进入_stopped_状态的。AudioPlayer在playing状态时,当以下情况发生时,其必须转移至_stopped_:
处理音频流时遇到问题且播控失败
客户端收到来自AVS的Stop指令时
收到clearBehavior
为CLEAR_ALL
的ClearQueue指令时
收到playBehavior
为REPLACE_ALL
的Play指令时
当处在_paused_或_buffer_underrun_状态下收到CLEAR_ALL
的ClearQueue
指令时,AudioPlayer必须转移至_stopped_状态。
无论何时,只要客户端收到Play
指令,AudioPlayer必须从_stopped_转移_playing_、开始播放音频流,且发送PlaybackStarted事件给AVS。
PAUSED:当在Content channel的音频是因为某个优先级更高的输出/入而需要暂停时 (例如用户或Alexa语音),AudioPlayer必须转移至_paused_状态。在优先级叫高的行为结束后,播放必须继续。对于音频输出入的优先级信息,请参考交互模型文档。
BUFFER_UNDERRUN:当客户端收到数据的速度低于数据被读取的速度时,AudioPlayer必须转移至_buffer_underrun_状态。AudioPlayer必须维持在此状态直到缓冲足够到继续播放,到时即该转移至_playing_状态。
FINISHED:当音频流结束播放时,AudioPlayer必须转移至_finished_状态。对于在playback queue中的每个音频流都必须这样处理。即便有多个音频流排队等著播放,客户端需要发送PlaybackFinished事件给AVS,并且当每个流结束播放时都需要接著将状态由_playing_状态转移至_finished_。
当以下情况发生时,AudioPlayer必须从_finished_转移至_playing_:
客户端收到Play指令
Playback queue中的下一个音频流开始播放时 (后续跟著上报PlaybackStarted event)
TmallGenie预期客户端在每个需要上下文的事件中都为当前播放的media item上报playerActivity
(状态) 与offsetInMilliseconds
。
{ "header": { "namespace": "AudioPlayer", "name": "PlaybackState" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}}, "playerActivity": "{{STRING}}" } }
参数 | 描述 | 型态 |
---|---|---|
token | 此值必须与目前所正在播放的媒体内容token相同。否则则必须与最后一个收到的Play指令中的token相同。 | 字串 |
offsetInMilliseconds | 目前音频播放状态的offset | 长整数 |
playerActivity | 用以识别AudioPlayer 的状态。允许值: IDLE, PLAYING, STOPPED, PAUSED, BUFFER_UNDERRUN, and FINISHED |
字串 |
Play
指令将发送给你的客户端以开始音频播放。此为一个由一个JSON指令与至多一个的二进制音频附件所构成的multipart报文。
包含在指令payload中的 playBehavior
参数可以被用来决定客户端该如何处理一个音频流的排队与播放行为。其允许值提供了客户端该进行哪些操作的指引:
REPLACE_ALL: 立即开始播放此Play指令所回传的音频流并取代目前正在使用的对列。当一个音频流正在播放而你收到一个 playBehavior
为 REPLACE_ALL
的 Play
指令时,你必须上报 PlaybackStopped
事件。
ENQUEUE: 在当前的音频队列中新增一个音频流。
REPLACE_ENQUEUED: 取代队列中的所有音频。但这不会影响目前正在播放的音频流。
Note:_ When adding streams to your playback queue, you must ensure that the token for the currently playing stream matches the expectedPreviousToken in the stream being added to the queue. If the tokens do not match the stream must be ignored. However, if no expectedPreviousToken is returned, the stream must be added to the queue._
{ "directive": { "header": { "namespace": "AudioPlayer", "name": "Play", "messageId": "{{STRING}}", "dialogRequestId": "{{STRING}}" }, "payload": { "playBehavior": "{{STRING}}", "audioItem": { "audioItemId": "{{STRING}}", "stream": { "url": "{{STRING}}", "offsetInMilliseconds": {{LONG}}, "expiryTime": "{{STRING}}", "progressReport": { "progressReportDelayInMilliseconds": {{LONG}}, "progressReportIntervalInMilliseconds": {{LONG}} }, "token": "{{STRING}}", } } } } }
Play
指令可能会有一个对应的二进制音频附件作为其multipart报文中的一部分。当二进制音频报文出现时,url
参数中的值将会包含 cid
前缀。
以下multipart标头将会出现在二进制音频附件之前:
Content-Type: application/octet-stream Content-ID: {{Audio Item CID}} {{BINARY AUDIO ATTACHMENT}}
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
dialogRequestId | 用以将在一个response中的指令关连至一个特定Recognize 事件的唯一ID。 |
字串 |
重要:你的客户端必须要能接受且能根据payload中的参数执行对应操作,而且不能因为JSON中有key/value缺失而出现问题。
参数 | 描述 | 型态 |
---|---|---|
playBehavior | 提供操作指引。允许值:REPLACE_ALL、ENQUEUE与REPLACE_ENQUEUED | 字串 |
audioItem | 包含针对audioItem的键值对 | 对象 |
audioItem.audioItemId | 识别audioItem的id | 字串 |
audioItem.stream | 包含针对进度上报的键值对 | 对象 |
audioItem.stream.url | 音频内容的位址。如果音频内容是二进制附件,此值会是一个代表该内容的唯一id,以 cid: 格式呈现。否则,此值会是一个远端http/https位址。 |
字串 |
audioItem.stream.offsetInMilliseconds | 用以指明客户端应该从音频流的哪边开始播放的时间戳。例如,如果这个值是0,即代表音频应该从音频的起点开始播放。任何其他值都代表播放应该开始的offset。 | 长整数 |
audioItem.stream.expiryTime | 用以表示此音频何时不可用的ISO 8601格式时间 | 字串 |
audioItem.stream.progressReport | 包含针对进度上报的键值对 | 对象 |
audioItem.stream.progressReport.progressReportDelayInMilliseconds | Specifies (in milliseconds) when to send the ProgressReportDelayElapsed event to AVS. ProgressReportDelayElapsed must only be sent once at the specified interval. Please note: Some music providers do not require this report. If the report is not required, progressReportDelayInMilliseconds will not appear in the payload. | 长整数 |
audioItem.stream.progressReport.progressReportIntervalInMilliseconds | Specifies (in milliseconds) when to emit a ProgressReportIntervalElapsed event to AVS. ProgressReportIntervalElapsed must be sent periodically at the specified interval. Please note: Some music providers do not require this report. If the report is not required, progressReportIntervalInMilliseconds will not appear in the payload. | 长整数 |
audioItem.stream.token | 用以表示此音频的token | 字串 |
在处理了Play
指令并开始播放其相关的音频流后,客户端 必须 上报PlaybackStarted
事件给TVS。
注意:对于TVS所发送的任一个URL,最多只能上报一次PlaybackStarted
事件。如果你收到了一个播放列表URL(由多个URL所组成),你也应该 只 上报一次PlaybackStarted
事件。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackStarted", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackNearlyFinished
事件必须要在客户端准备好缓冲/下载playback queue中的下一个音频时上报。客户端必须确定此事件的发送时间点是在当前播放音频的 PlaybackStarted
事件之后上报的。TmallGenie将会给予以下回复之一:
包含了下一个音频的 Play
指令
HTTP 204回应码
_Tip:作为最佳实践,你可以等到前一首歌已经buffered好了才发出PlaybackNearlyFinished事件。这能降低播放时间超过expiryTime的风险,并且能降低因为下载与同时处理多个Play指令而造成音乐播放抖动的可能性。 _
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackNearlyFinished", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
如果 Play
指令中存在 progressReportDelayInMilliseconds
,则必须将 ProgressReportDelayElapsed
事件发送到 TmallGenie 。事件必须从流的开始按指定的间隔发送一次(而不是从 offsetInMilliseconds
)。例如,如果 Play
指令包含 progressReportDelayInMilliseconds
的值为 20000
,则 ProgressReportDelayElapsed
必须从轨道的开始发送20,000毫秒来发送事件。但是,如果 Play
指令包含 offsetInMilliseconds
的价值 10000
和progressReportDelayInMilliseconds
价值 20000
,该事件必须发送10000毫秒为播放。这是因为进度报告是从流的开始而不是 Play
指令的偏移量发送的。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "ProgressReportDelayElapsed", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
如果 Play
指令中存在 progressReportIntervalInMilliseconds
,则必须将 ProgressReportIntervalElapsed
事件发送到 TmallGenie。事件必须从流的开始(而不是从 offsetInMilliseconds
)开始,按照指定的间隔定期发送。例如,如果 Play
指令包含一个值为 20000
的 progressReportIntervalInMilliseconds
,那么从跟踪开始的时间起,ProgressReportIntervalElapsed
事件必须发送20,000毫秒,并且每隔20,000毫秒发送一次,直到流结束。如果 Play
指令包含一个 offsetInMilliseconds
值为 10000
, progressReportIntervalInMilliseconds
值为 20000
,则必须从播放开始发送10,000毫秒,之后每隔20,000毫秒发送一次,直到流结束。这是因为指定的间隔是从流的开始,而不是 Play
指令的偏移量。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "ProgressReportIntervalElapsed", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackStutterStarted
事件必须被发送到 TmallGenie,是在 PlaybackStarted
事件之后,客户端的 AudioPlayer
组件的数据比读取数据慢时。一旦发送了这个事件,组件必须转换到 buffer_underrun
状态,并保持这种状态,直到缓冲区足够满,可以恢复播放。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackStutterStarted", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackStutterFinished
事件必须发送到 TmallGenie 时,缓冲区已足够恢复播放流。PlaybackStarted
恢复音频播放时, TmallGenie 不会期望后续事件。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackStutterFinished", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}}, "stutterDurationInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
stutterDurationInMilliseconds | 标识卡顿的持续时间(毫秒)。 | 长整数 |
PlaybackFinished
事件必须在客户端结束音频的播放时上报给TVS。
当以下情况时 不会 上报此事件:
播放被停止 (无论是本地自行停止或作为 Stop
指令的执行结果)
在音频之间切换 (上一首/下一首)
注意:对于TVS所发送的任一个URL,最多只能上报一次PlaybackFinished
事件。如果你收到了一个播放列表URL(由多个URL所组成),你也应该 只 上报一次PlaybackFinished
事件。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackFinished", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
https://developer.amazon.com/de/docs/alexa-voice-service/audioplayer.html#playbackfailed
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackFailed", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "currentPlaybackState": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}}, "playerActivity": "{{STRING}}" }, "error": { "type": "{{STRING}}", "message": "{{STRING}}" } } } }
Instructs your client to stop playback of an audio stream. Your clientmay receive this directive as the result of a voice request or physicalcontrol
{ "directive": { "header": { "namespace": "AudioPlayer", "name": "Stop", "messageId": "{{STRING}}", "dialogRequestId": "{{STRING}}" }, "payload": { } } }
PlaybackStopped
事件必须在客户端收到以下指令之一并且停止了音频播放时上报给TVS:
Stop
指令
playBehavior
为 REPLACE_ALL
的 Play
指令
clearBehavior
为 CLEAR_ALL
的 ClearQueue
指令
注意:这个事件只能在音频因为以上指令而终止时上报。一般来说,这会是因为用户的行为造成的。此事件 不能 在音频正常结束时上报。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackStopped", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackPaused
事件必须在客户端为了配合较高优先级的输出入而必须暂时停止在Content channel中播放的音频时上报。该播放行为必须在高优先级的操作完成后继续进行,同时需要上报 PlaybackResumed
事件。
注意:PlaybackPaused
应该要在 Recognize
事件之后上报以减少延迟。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackPaused", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackResumed
事件必须在音频继续播放时上报给TVS。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackResumed", "messageId": "{{STRING}}" }, "payload": { "token": "{{STRING}}", "offsetInMilliseconds": {{LONG}} } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |
参数 | 描述 | 型态 |
---|---|---|
token | 由Play 指令所提供的opaque token。 |
字串 |
offsetInMilliseconds | 表示某个音轨目前的offset。上报时此数值必须等于或大于0,不允许负值。 | 长整数 |
PlaybackQueueCleared
事件必须在客户端处理完 ClearQueue
指令后上报给TVS。
{ "event": { "header": { "namespace": "AudioPlayer", "name": "PlaybackQueueCleared", "messageId": "{{STRING}}" }, "payload": { } } }
参数 | 描述 | 型态 |
---|---|---|
messageId | 用以代表一个特定message的唯一ID。 | 字串 |