AudioPlayer音频播放
摘要
AudioPlayer指令从技能发送给DuerOS,对端上进行音乐播放控制。在DuerOS收到该指令后,会经过一系列处理解析为端上对应的播放指令。在云端下发AudioPlayer指令后,端上开始音乐播放操作。音乐播放会触发一系列事件上报到云端。这些指令和事件分别是:
- AudioPlayer.Play指令
- 播放。
- AudioPlayer.Stop指令
- 停止。
- AudioPlayer.PlaybackStarted事件
- 播放开始。
- AudioPlayer.PlaybackStopped事件
- 播放暂停。
- AudioPlayer.PlaybackFinished事件
- 播放结束,即一首歌播放完后上报的事件。
- AudioPlayer.PlaybackFailed事件
- 当设备端播放Audio item发生错误时上报此事件。
- AudioPlayer.PlaybackNearlyFinished事件
- 在播放即将结束时上报的事件。
- AudioPlayer.ProgressReportIntervalElapsed事件
- AudioPlayer用来定期上报播放状态的事件。
AudioPlayer.Play指令
用于在设备端播放一个音频。
消息样例
{
"type": "AudioPlayer.Play",
"playBehavior": "{{STRING}}"
"audioItem": {
"stream": {
"url": "{{STRING}}",
"streamFormat": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}},
"token": "{{STRING}}",
"progressReportIntervalMs": {{LONG}}
},
"playerInfo": {
"content": {
"title": "{{STRING}}",
"titleSubtext1": "{{STRING}}",
"titleSubtext2": "{{STRING}}",
"language": "{{STRING}}",
"effect": {
"bpm": {{INT}},
"landscapeVideoUrl": "{{STRING}}",
"portraitVideoUrl": "{{STRING}}",
"fontColor": "{{STRING}}",
"fontFamily": "{{STRING}}",
"fontSize": "{{STRING}}",
"landscapeBackgroundImageUrl": "{{STRING}}",
"portraitBackgroundImageUrl": "{{STRING}}",
"animation": {
"id": "{{STRING}}",
"url": "{{STRING}}",
"md5": "{{STRING}}"
},
},
"lyric": {{LyricStructure}},
"mediaLengthInMilliseconds": {{LONG}},
"art": {{ImageStructure}},
"provider": {
"name": "{{STRING}}",
"logo": {{ImageStructure}}
}
}
"controls": [
{{ControlStructure}},
{{ControlStructure}},
......
]
}
}
}
参数说明
- type
- AudioPlayer指令类型,即"AudioPlayer.Play"。
- playBehavior
- REPLACE_ALL
- 清空播放列表,立即播放指令关联的音频。例如,"播放周杰伦的歌曲"、"播放郭德纲的相声"、"下一首"、"上一首"。
- REPLACE_ENQUEUED
- 清空播放列表,同时把指令关联的音频加到播放列表,但当前播放的歌曲不受影响。例如,"这首歌播放完后播放周杰伦的歌曲",“单曲循环、列表循环、随机播放”。
- ENQUEUE
- 把指令关联的音频添加到播放列表末尾,当前播放的音频不受影响,下一首预取。
- REPLACE_ALL
- audioItem
- 音频的详细信息。
- audioItem.stream
- 音频流相关的信息。
- audioItem.stream.url
- 音频流地址。
- audioItem.stream.streamFormat
- 播放的音频流的格式,例如"MP3"。
- audioItem.stream.offsetInMilliSeconds
- 音频播放起始点。
- audioItem.stream.token
- 唯一标识此次directive中播放的音频流,设备端会存储这个值,在音频播放期间,产生的所有事件的端状态中会携带这个值。
- audioItem.stream.progressReportIntervalMs
- 定时上报ProgressReportIntervalElapsed事件的间隔时间。
- audioItem.playInfo
- 音频展现的相关信息,该项可选。在有屏设备端播放音频资源时,会对playInfo的信息进行展现,如播放音乐时,展现歌词、歌手图片等。在无屏设备端playInfo不生效。
- audioItem.playInfo.content
- 音频展现信息的具体内容。
- audioItem.playInfo.content.title
- 音频的标题,比如歌曲名“告白气球”。
- audioItem.playInfo.content.titleSubtext1
- 音频子标题1,比如歌手名“周杰伦”。
- audioItem.playInfo.content.titleSubtext2
- 音频子标题2,比如专辑名“周杰伦的床边故事”。
- (optional) audioItem.playInfo.content.language
- 语言,当前支持两种语言:zh(中文),en(英文)。参考 ISO 639-1
- (optional) audioItem.playInfo.content.effect.bpm
- 音乐每分钟节拍数,参考BPM
- (optional) audioItem.playInfo.content.effect.landscapeVideoUrl
- 播放器横屏模式特效背景视频URL
- (optional) audioItem.playInfo.content.effect.portraitVideoUrl
- 播放器竖屏模式特效背景视频URL
- (optional) audioItem.playInfo.content.effect.fontColor
- 播放器特效歌词字体颜色,格式为#RGB,如#AABBCC,端上默认颜色#1A1A1A
- (optional) effect.fontFamily
- 播放器特效歌词字体,如果该字段不存在或者值为空,则端上使用系统字体。当前可选值:
- duer_cang_er_yu_mo
- duer_qian_tu_ma_ke
- duer_qian_tu_xian_mo
- duer_rui_zhi_zhen_yan
- duer_zhuang_jia_ming_chao
- 播放器特效歌词字体,如果该字段不存在或者值为空,则端上使用系统字体。当前可选值:
- (optional) effect.fontSize
- 播放器特效歌词字体大小,如果该字段不存在或值为空,则端上自行计算
- (optional) effect.landscapeBackgroundImageUrl
- 播放器横屏模式特效背景图片URL,当有背景动效时,通常为背景动效的首帧截图
- (optional) effect.portraitBackgroundImageUrl
- 播放器竖屏模式特效背景图片URL,当有背景动效时,通常为背景动效的首帧截图
- (optional) effect.animation.id
- 当前逐句歌词pag动效模板集合id
- (optional) effect.animation.url
- 动效集合的压缩包地址
- (optional) effect.animation.md5
- 动效集合压缩包的md5校验值(两个作用:1.校验压缩包下载是否完整,2.动效是否有更新)
- audioItem.playInfo.content.lyric
- 歌词信息,请参考LyricStructure结构体。
- audioItem.playInfo.content.mediaLengthInMilliseconds
- 音频流的长度,单位为ms。优先使用设备端获取的音频流的实际长度,这里的音频流长度主要应用Companion App等场景的渲染。
- audioItem.playInfo.content.art
- 音频封面图片,比如音乐里专辑的封面图,请参考ImageStructure的定义。
- audioItem.playInfo.content.provider
- 资源提供方信息。
- audioItem.playInfo.content.provider.name
- 资源提供方的名字,比如百度音乐、QQ音乐、虾米音乐等。
- audioItem.playInfo.content.provider.logo
- 资源提供方的logo,请参考ImageStructure的定义。
- audioItem.playInfo.controls
- 音频播放使用的控件列表。点击链接了解音频播放支持的控件类型。
说明:
- 该指令需要在设备端麦克关闭的情况下使用。下面两种情况下麦克风会关闭,可以返回AudioPlayer.Play指令。
- audioItem.playInfo用于渲染音频播放器的主界面,在有屏设备端播放音频资源时,展现音频相关信息,如歌词、歌手图片等。该字段在无屏设备端不生效。
LyricStructure
定义歌词的结构。
消息样例
{
"url": "{{STRING}}",
"format": {{ENUM}}
}
参数说明
- url
- 歌词url地址,支持http协议和cid格式(即内容直接附加在指令中)。 在AudioPlayer.Play指令中只支持http地址。
- format
- 歌词的格式,支持的格式类型:
- LRC: 参考LRC
- DRC: 逐字/词歌词
ImageStructure
定义图片结构。
消息样例
{
"src": "{{STRING}}"
}
参数说明
- src
- 图片地址。
AudioPlayer.Stop指令
用于停止设备端的音频播放。
消息样例
{
"type": "AudioPlayer.Stop"
}
参数说明
- type:
- AudioPlayer指令类型,即"AudioPlayer.Stop"。
AudioPlayer.PlaybackStarted事件
客户端开始播放的时候,需要上报此事件。
消息样例
{
"type": "AudioPlayer.PlaybackStarted",
"requestId": "{{STRING}}",
"timestamp": {{STRING}},
"token": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.PlaybackStarted"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- timestamp
- 请求时间戳,单位是秒,一个全部是数字的字符串。
- token
- 对应到播放的音频id。
- offsetInMilliSeconds
- 事件上报时音频流的播放点。
PlaybackStopped事件
用户说"暂停播放"、 "停止播放"后,会收到Stop指令,客户端执行完Stop指令后,即暂停播放后,需要上报此事件,云端会保存断点,供下一次继续播放使用。
消息样例
{
"type": "AudioPlayer.PlaybackStopped",
"requestId": "{{STRING}}",
"timestamp": {{STRING}},
"token": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.PlaybackStopped"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- timestamp
- 请求时间戳,单位是秒,一个全部是数字的字符串。
- token
- 对应到播放的音频id。
- offsetInMilliSeconds
- 事件上报时音频流的播放点。
PlaybackNearlyFinished事件
这个事件用来获取下一首歌曲,云端收到这个事件后,返回下一首歌曲对应的Play指令,playBehavior选项设为ENQUEUE, 指示客户端加入到本地列表中,利用此事件,客户端可以实现下一首的预取。这个事件的上报时机取决于客户端,可以在歌曲播放的中间发送,也可以剩余几秒钟的时候发送。如果不需要预取,也可以在歌曲播放完毕后上报此事件。但必须保证:
- PlaybackNearlyFinished必须在PlaybackStarted事件发送完毕后才上报。
- 一首歌曲只发送一次PlaybackNearlyFinished事件。
消息样例
{
"type": "AudioPlayer.PlaybackNearlyFinished",
"requestId": "{{STRING}}",
"timestamp": {{STRING}},
"token": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.PlaybackNearlyFinished"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- timestamp
- 请求时间戳,单位是秒,是一个全部是数字的字符串。
- token
- 对应到播放的音频id。
- offsetInMilliSeconds
- 事件上报时音频流的播放点。
PlaybackFinished事件
当且仅当歌曲正常播放到末尾后,上报此事件。注意如果被其它指令打断比如“下一首”、“上一首”导致没有播放到末尾的,不上报此事件。
消息样例
{
"type": "AudioPlayer.PlaybackFinished",
"requestId": "{{STRING}}",
"timestamp": {{STRING}},
"token": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.PlaybackFinished"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- timestamp
- 请求时间戳,单位是秒,是一个全部是数字的字符串。
- token
- 对应到播放的音频id。
- offsetInMilliSeconds
- 事件上报时音频流的播放点。
PlaybackFailed事件
当设备端播放audio item发生错误时上报此事件。
事件中的token有可能与正在播放中的audio item的token不一致,比如正在播放一个audio item,并要开始缓冲下一个audio item时下一个audio item的缓冲出现错误。
消息样例
{
"type": "AudioPlayer.PlaybackFailed",
"requestId": "{{STRING}}",
"token": "{{STRING}}",
"error": {
"type": "{{STRING}}",
"message": "{{STRING}}"
}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.PlaybackFailed"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- token
- 发生错误的audio item的token
- error.type
- 错误类型,取值如下
"MEDIA_ERROR_UNKNOWN"
: 未知错误"MEDIA_ERROR_INVALID_REQUEST"
: stream服务端返回请求无效 (可能的情况有bad request, unauthorized, forbidden, not found等等)"MEDIA_ERROR_SERVICE_UNAVAILABLE"
: 设备端无法连接stream服务端"MEDIA_ERROR_INTERNAL_SERVER_ERROR"
: stream服务端接受请求,但未能正确处理"MEDIA_ERROR_INTERNAL_DEVICE_ERROR"
: 设备端内部错误
- 错误类型,取值如下
- error.message:
- 错误描述,仅用于打印日志;如果有HTTP相关的错误,也应该包含在本错误消息中,以便排查问题。
ProgressReportIntervalElapsed事件
如果Play指令设置了progressReportIntervalMs的值,那么客户端需要周期性的每隔一段时间上报一次当前的播放进度,直到歌曲播放结束。注意歌曲开始播放和歌曲结束播放的时候,可以不上报这个事件。
下面两种情况,上报事件时所处的播放位置是一样的,跟offsetInMilliSeconds的值没有关系,因为是从音频流的0位置算起。云端收到这个事件后,可能会返回给客户端一条指令,需要客户端执行之,比如AdjustVolume指令、Stop指令等。利用这个特性可以实现助眠模式。
- 情况1:假如progressReportIntervalMs的值为3000,Play指令的offsetInMilliSeconds值为0,从音频流的0位置算起,如果播放位置到达3000的整数倍,就上报一次事件。
- 情况2:假如progressReportIntervalMs的值为3000,Play指令的offsetInMilliSeconds值为1000,从音频流的0位置算起,如果播放位置到达3000的整数倍,就上报一次事件。
消息样例
{
"type": "AudioPlayer.ProgressReportIntervalElapsed",
"requestId": "{{STRING}}",
"timestamp": {{STRING}},
"token": "{{STRING}}",
"offsetInMilliSeconds": {{LONG}}
}
参数说明
- type
- 请求类型,即字符串"AudioPlayer.ProgressReportIntervalElapsed"。
- requestId
- 标识本次请求的唯一ID。如果有问题反馈,可以附带提供给DuerOS开发人员。
- timestamp
- 请求时间戳,单位是秒,是一个全部是数字的字符串。
- token
- 对应到播放的音频id。
- offsetInMilliSeconds
- 事件上报时音频流的播放点。
音频播放示例
{
"version": "2.0",
"context": {
"user": {
"userId": "xxx"
},
"System": {
"application": {
"applicationId": "audioplayer"
}
}
},
"request": {
"type": "AudioPlayer.PlaybackStarted",
"requestId": "33c78c8f-22db-4d6a-bfd5-075d264377b7",
"timestamp": "1501127440",
"token": "12329898321",
"offsetInMilliSeconds": 1000
}
}