# 音频播放器_v1.1
- 音频播放器控件的状态
- Play 指令
- PlaybackStarted事件
- PlaybackNearlyFinished 事件
- ProgressReportDelayElapsed 事件
- ProgressReportIntervalElapsed 事件
- PlaybackStutterStarted 事件
- PlaybackStutterFinished 事件
- PlaybackFinished 事件
- PlaybackFailed 事件
- Stop指令
- PlaybackStopped 事件
- PlaybackPaused 事件
- PlaybackResumed 事件
- ClearQueue 指令
- PlaybackQueueCleared 事件
- StreamMetadataExtracted 事件
本接口提供通过语音控制音频播放的指令,和管理音频播放进程的事件。
# 音频播放器控件的状态
IDLE(空闲状态): 音频播放器只有在设备初始通电或初始化之后,未接收过Play
指令之前,才是空闲状态。
PLAYING(正在播放): 当设备接收到Play
指令开始播放音频时,音频播放器的状态必须进入PLAYING状态。一般来说,音频播放器在当前播放列表播放完成之前需要一直保持PLAYING状态,另外在向服务端上报播放进度和音频元数据时,也需要保持PLAYING状态。当客户端遇到以下情况时,音频播放器将退出PLAYING状态:
1.接收到Stop
指令
2.缓冲音频文件出错
3.播放失败
STOPPED(播放停止): 出现以下几种情况时,音频播放器必须从当前状态切换至STOPPED状态:
- PLAYING状态时:音频流出现问题导致播放失败。
- PLAYING状态时:客户端接收到云端发送的
Stop
指令。 - PLAYING状态时:客户端接收到
ClearQueue
指令,指令中的clearBehavior
参数的值是CLEAR_ALL
- PLAYING状态时:客户端接收到
Play
指令,指令中的playBehavior
参数的值是REPLACE_ALL
- PAUSED状态或BUFFER_UNDERRUN状态时:客户端接收到
ClearQueue
指令,指令中的clearBehavior
参数的值是CLEAR_ALL
PAUSED(播放暂停): 优先级更高的通道(对话通道、提醒通道)从非活跃状态变为活跃状态时,音频播放器应该进入PAUSED状态。当其他通道变为非活跃时,音频应该继续播放,音频播放器状态变为PLAYING。
BUFFER_UNDERRUN(缓冲): 当设备端接收流数据的速度比播放速度慢时,进入BUFFER_UNDERRUN状态,直至缓冲完成后回复到PLAYING状态。
FINISHED(播放完成): 当播放列表播放完成时,客户端上报PlaybackFinished
事件至服务端,并将音频播放器切换到FINISHED状态。当设备端存在多个待播放的播放列表时,一个播放列表播放完成,音频播放器需切换至FINISHED状态,随后开始下一个播放列表的播放,音频播放器重新切换至PLAYING状态。
# Play 指令
Play
指令控制设备端的音频播放,指令包含一个所要播放的audio item,以及控制播放行为的playBehavior
参数。
# 消息样式
{
"directive": {
"header": {
"namespace": "AudioPlayer",
"name": "Play",
"messageId": "e52e7a4c...",
"dialogRequestId": "49687be..."
},
"payload": {
"playBehavior": "REPLACE_ENQUEUED",
"audioItem": {
"audioItemId": "2698f663288aedebab0f4773727448c4",
"stream": {
"url": "https://www.iflyos.cn/example...",
"streamFormat": "AUDIO_MPEG",
"offsetInMilliseconds": 60000,
"expiryTime": "2018-08-06T16:13Z",
"progressReport": {
"progressReportDelayInMilliseconds": 60000,
"progressReportIntervalInMilliseconds": 60000
},
"token": "S0wiXQZ1rVBkov...",
"expectedPreviousToken": "g7i2dciPYEWEigs4b..."
}
}
}
}
}
# 二进制音频附件
Play
指令有可能含有相关联的二进制音频附件,在这种情况下,payload中的audioItem.stream.url
将以cid:{id}
的形式出现。
二进制音频的文件头:
Content-Type: application/octet-stream
Content-ID: {{Audio Item CID}}
{{BINARY AUDIO ATTACHMENT}}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
dialogRequestId | 客户端必须为recognize 请求创建的唯一ID,此参数用于关联响应特定Recognize 事件发送的指令 | String |
# Payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
playBehavior | 用来决定客户端怎么处理播放队列。可取值如下: REPLACE_ALL: 立即停止当前播放的音频(发送 PlaybackStopped 事件至服务端)并清除当前播放队列,立即播放指令中的包含的audio item。ENQUEUE: 将指令中的audio item添加到当前播放队列的尾部。 REPLACE_ENQUEUED: 替换播放队列中的所有audio item,但不影响当前正在播放的audio item。 | String | 是 |
audioItem | 包含所要播放的音频资源 | Object | 是 |
audioItem.audioItemId | 资源ID | String | 是 |
audioItem.stream | 云端音频流信息 | Object | 是 |
audioItem.stream 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
url | 音频文件的播放地址。一般情况下是http/https地址,当音频内容是二进制音频附件时,格式为cid:{id} | String | 是 |
streamFormat | 只有音频内容是二进制音频附件资源时,这个键才存在。 可取值: ADUIO_MPEG | String | 否 |
offsetInMilliseconds | 客户端从指定的offset开始进行播放 | Long | 是 |
expiryTime | 音频流失效的日期时间,使用ISO8601格式 | String | 是 |
progressReport | 播放状态报告要求 | Object | 否 |
progressReport. progressReportDelayInMilliseconds | 播放了一定时间后向服务端发送ProgressReportDelayElapsed 事件。该参数不存在时不需要发送事件 | Long | 否 |
progressReport. progressReportIntervalInMilliseconds | 每间隔一定时间后向服务端发送ProgressReportIntervalElapsed 事件。该参数不存在时不需要发送事件 | Long | 否 |
token | 代表该资源的 token | String | 是 |
expectedPreviousToken | 代表前一个音频资源的token 若该参数存在时需要特别注意: 在playBehavior为ENQUEUE时,expectedPreviousToken应该与当前播放队列末尾audio item中的token一致 在playBehavior为REPLACE_ENQUEUED时,expectedPreviousToken应该与当前正在播放的audio item中的token一致 若不一致则不执行本 Play 指令。 | String | 否 |
# PlaybackStarted事件
当客户端处理接收到的Play
指令并开始播放audio item时上报该事件至服务端。
注意
一个Play
指令只需要上报一次PlaybackStarted
事件,即使指令中包含多个音频文件。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackStarted",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# Payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 开始播放的资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# PlaybackNearlyFinished 事件
当播放快要结束前,或者准备缓冲/下载下一组资源的时候,上报本事件。你需要确认该事件在这组音频资源的PlaybackStarted
事件之后上报。云端可能会返回2种情况:
- 返回一个包含下一组音频资源的Play指令
- HTTP 204 响应
为了更好的体验,你应该考虑在上一组音频完全缓冲好之后再发送该事件,否则可能会因为超过当前播放的音频资源的有效时间从而无法继续缓冲当前文件,也可能因为同时在下载和处理多个Play
指令而造成的当前播放的音频资源在播放过程中断断续续。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackNearlyFinished",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 即将完成播放的资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# ProgressReportDelayElapsed 事件
如果Play
指令中要求发送该事件,那么客户端必须在音频播放到特定时间时上报该事件到服务端。若Play
指令中offsetInMilliseconds=10000
,progressReportDelayInMilliseconds=30000
,即音频从10000ms的位置处开始播放,播放20000ms后到达30000ms的位置,此时上报该事件。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "ProgressReportDelayElapsed",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# ProgressReportIntervalElapsed 事件
如果Play
指令中要求发送该事件,那么客户端必须在音频资源开始播放到特定位置时第一次上报该事件到服务端,并每间隔一段特定时间就上报一次该事件至服务端,直至整个音频资源播放结束。若Play
指令中offsetInMilliseconds=10000,progressReportIntervalInMilliseconds=30000,即音频从10000ms的位置处开始播放,播放20000ms后到达30000ms的位置,此时上报该事件,此后每过30000ms就上报一次。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "ProgressReportIntervalElapsed",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# PlaybackStutterStarted 事件
在PlaybackStarted
事件之后,当音频播放出现断断续续的情况时,必须上报该事件,此时音频播放器的状态变为BUFFER_UNDERRUN
,直到音频文件缓冲到能够继续播放时恢复。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackStutterStarted",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# PlaybackStutterFinished 事件
当音频缓冲到能够继续播放时,该事件需要上报至服务端(不需要再次上报PlaybackStarted
事件),此时音频播放器的状态变为PLAYING。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackStutterFinished",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000,
"stutterDurationInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
stutterDurationInMilliseconds | 这一次断断续续的状态的持续时间,毫秒为单位 | Long | 是 |
# PlaybackFinished 事件
当客户端将音频资源播放完成时,上报该状态至服务端。若音频播放被停止(Stop
指令或设备本地操作)或上一首下一首切换时,不上报该事件。
注意
一个Play
指令只需要上报一次PlaybackFinished
事件,即使指令中包含多个音频文件。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackFinished",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 播放完成时的时间,毫秒为单位 | Long | 是 |
# PlaybackFailed 事件
只要客户端尝试播放音频的时候发生了错误就需要上报该事件至服务端。该事件中的token有可能与当前正在播放中的音频的token不一致,比如正在播放一个音频,并要开始缓冲下一个音频时缓冲出现错误。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackFailed",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"currentPlaybackState": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000,
"playerActivity": "PLAYING"
},
"error": {
"type": "MEDIA_ERROR_UNKNOWN",
"message": "未知错误"
}
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
currentPlaybackState | 当前播放的音频的状态 | Object | 是 |
currentPlaybackState. token | 当前正在播放的音频的token | String | 是 |
currentPlaybackState. offsetInMilliseconds | 当前正在播放的音频的播放进度,毫秒为单位 | Long | 是 |
currentPlaybackState. playerActivity | 当前音频播放器的状态。 可取值: PLAYING, STOPPED, PAUSED, FINISHED, BUFFER_UNDERRUN, IDLE | String | 是 |
error | 错误信息 | Object | 是 |
error.type | 错误类型,具体类型见下表 | String | 是 |
error.message | 错误描述,仅用于打印日志。如果有HTTP相关的错误,也应该包含在本错误消息中,以便排查问题。 | String | 是 |
# Error Types
错误类型值 | 描述 |
---|---|
MEDIA_ERROR_UNKNOWN | 发生了未知错误 |
MEDIA_ERROR_INVALID_REQUEST | 请求无效。可能的情况有:bad request, unauthorized, forbidden, not found等。 |
MEDIA_ERROR_SERVICE_UNAVAILABLE | 设备端无法获取音频文件 |
MEDIA_ERROR_INTERNAL_SERVER_ERROR | 服务端接收了请求但未能正确处理 |
MEDIA_ERROR_INTERNAL_DEVICE_ERROR | 设备端内部错误 |
# Stop指令
当用户通过语音指令或设备操作请求停止音频播放时,设备端将会收到这个指令。设备端收到指令后应停止音频播放。
# 消息样式
{
"directive": {
"header": {
"namespace": "AudioPlayer",
"name": "Stop",
"messageId": "e52e7a4c...",
"dialogRequestId": "49687be..."
},
"payload": {
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
dialogRequestId | 客户端必须为recognize 请求创建的唯一ID,此参数用于关联响应特定Recognize 事件发送的指令 | String |
# PlaybackStopped 事件
客户端收到以下指令并停止音频播放后,必须上报该事件至服务端:
Stop
指令playBehavior
参数值等于REPLACE_ALL
的Play
指令clearBehavior
参数值等于CLEAR_ALL
的ClearQueue
指令
注意
只有在设备端收到上述指令并停止音频播放时才上报该事件,如果音频播放完毕正常结束,应该上报PlaybackFinished
事件。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackStopped",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# PlaybackPaused 事件
当设备端的音频通道被优先级更高的通道(对话通道、提醒通道)打断暂停时,设备端应该上报该事件至服务端。当其他通道变为非活跃时,音频应该继续播放,此时上报PlaybackResumed
事件。
*注意:发生语音输入时,为了减少语音交互的延迟,应该先上报Recognize
事件,再上报PlaybackPaused
事件。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackPaused",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# PlaybackResumed 事件
在设备上报PlaybackPaused
事件后,当设备端继续音频播放时,设备端应该上报该事件至服务端。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackResumed",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"offsetInMilliseconds": 60000
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
offsetInMilliseconds | 当前的播放进度,毫秒为单位 | Long | 是 |
# ClearQueue 指令
设备端收到该指令后,应该清除本地的音频播放列表。
# 消息样式
{
"directive": {
"header": {
"namespace": "AudioPlayer",
"name": "ClearQueue",
"messageId": "e52e7a4c...",
"dialogRequestId": "49687be..."
},
"payload": {
"clearBehavior": "CLEAR_ENQUEUED"
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
dialogRequestId | 客户端必须为recognize 请求创建的唯一ID,此参数用于关联响应特定Recognize 事件发送的指令 | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
clearBehavior | 清除播放列表的方式。 可取值: CLEAR_ENQUEUED: 清除整个播放列表,当前正在播放的音频不受影响。 CLEAR_ALL: 清除整个播放列表,并停止当前正在播放的音频 | String | 是 |
# PlaybackQueueCleared 事件
在设备端处理了ClearQueue
指令后,必须上报该事件到服务端。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackQueueCleared",
"messageId": "e52e7a4c..."
},
"payload": {
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# Payload 参数
payload为空。
# StreamMetadataExtracted 事件
当设备端开始播放音频文件时,如果音频资源附带元数据,设备端需要把接收到元数据以键值对的形式作为JSON对象,上报该事件到服务端。在这个JSON对象中,字符串和数字作为JSON 字符串,布尔值作为JSON 布尔值,若包含二进制数据(如图片、附件、应用数据等),则二进制数据不用上报。
# 消息样式
{
"event": {
"header": {
"namespace": "AudioPlayer",
"name": "StreamMetadataExtracted",
"messageId": "e52e7a4c..."
},
"payload": {
"token": "S0wiXQZ1rVBkov...",
"metadata": {
"key-1": "value-1",
"key-2": true,
"key-3": "1"
}
}
}
}
# header 参数
参数名 | 说明 | 类型 |
---|---|---|
messageId | 代表一条message的唯一ID | String |
# payload 参数
参数名 | 说明 | 类型 | 必须出现 |
---|---|---|---|
token | 该资源的token,与Play 指令中token对应 | String | 是 |
metadata | 元数据的键值对 | Object | 是 |
← 闹钟和提醒_v1.0 播放控制_v1.0 →