主题
6.2 媒体资源接入
媒体资源是 JoyInside 的内容类能力,涵盖有声书和音乐两大类,共用一套独立协议。与普通语音对话的差异:云端除回复 TTS 外,还会下发媒体资源(mp3 链接)让端侧流式播放,并需要端侧上报播放状态(开播 / 停播 / 心跳)。
JoyInside 内置有声书、音乐智能体及资源,推荐优先使用;也支持对接三方媒体资源(见 7.2 外部媒体资源接入)。
注意事项:
资源返回播放地址字段audioURL,默认域名是storage.360buyimg.com。 如果默认域名因网络原因导致无法正常使用时,可联系JoyInside 运营团队配置备用CDN域名:audio.joyinside.com。
若端侧设备使用4G等物联网卡播放媒体资源,需要向运营商申请域名加白名单(见下文)
物联网卡申请域名加白名单(点击展开)
text
## 一级域名
joyinside.com
360buyimg.com
## 二级域名如下
api.joyinside.com(获取token需要用此域名)
ws.joyinside.com(websocket建连需要用此域名)
audio.joyinside.com(后续有声书、歌曲资源的链接都用此域名)
storage.360buyimg.com(现在有声书、歌曲资源的链接用此域名)
img10.360buyimg.com(现在有声书封面的图片链接用此域名,如果设备不需要封面的话可以不加)6.2.1 资源类型:有声书 vs 音乐
媒体资源在协议层复用同一套事件(AUDIO_BOOK_*),通过资源本身区分类型:
| 类型 | 内容形态 | 自动续播逻辑 | 典型场景 |
|---|---|---|---|
| 有声书 | 章节化长音频 | 按章节顺序续播;如果章节播完后,自动播放下一本书 | "播放三体第五章" |
| 音乐 | 单曲 | 按播放列表顺序续播;列表播完可基于 query 重新检索 | "来一首欢快的歌" |
端侧无需感知类型差异,收到
AUDIO_BOOK_PLAY下行即按流式播放处理;类型差异由服务端在续播策略和资源检索层面处理。
6.2.2 两种接入模式: 手动按键 vs 连续对话
媒体资源接入分两个版本,核心差异在 feature 参数:
| 版本 | 建联参数 | 模式 | 说明 |
|---|---|---|---|
| 手动按键模式 | feature=AUDIO_BOOK + clientType=AUDIO_BOOK | 按键触发播放 | 类似对讲机,按键控制播放 / 停止 |
| 连续对话模式 | feature=AUDIO_BOOK_V2 | 语音连续对话 | 集成在自由模式对话中,语音即可控制播放 |
手动按键模式/连续对话模式 仅
feature参数不同,事件字段协议完全一致。新接入推荐 连续对话模式(体验更自然)。
feature参数名沿用AUDIO_BOOK,但同时承载有声书和音乐能力,不必单独开启。
6.2.3 接入整体流程概览
媒体资源接入涉及建联、TTS 播报、资源播放、心跳保活、播控响应五个环节,端侧按下图顺序推进接入:
注意事项
- 在接入播控事件前,必须先接入媒体资源心跳事件(
AUDIO_BOOK_PING/AUDIO_BOOK_PONG)。服务端依赖心跳判定端侧真实播放状态,心跳最大间隔时间为2s;若心跳缺失,播控指令(暂停 / 上一集 / 下一集等)在服务端会被判定为「非播放态」,从而按点播 / 闲聊语义处理,导致播控失效。 - 建议遵守「先 TTS 串场词,后播媒体资源」的顺序。服务端会先下发串场词 TTS(
TTS_SENTENCE_START/TTS/TTS_COMPLETE),再下发AUDIO_BOOK_PLAY;端侧必须等串场词播放完成后再拉起 mp3 流式播放,否则会出现串场词与有声书 / 音乐叠音、或串场词被截断的问题。 - 停播事件(
AUDIO_BOOK_STOP上行)必须携带真实播放进度(progress单位为秒,finish标识是否完播)。无论是资源自然播完、用户唤醒中断、还是服务端下发停止,端侧都必须上报,否则会导致续播定位错误、历史进度丢失、续播资源无法命中。
6.2.4 端侧接入概览
建连增加参数
- WS 连接时增加参数
feature=AUDIO_BOOK_V2表示开启媒体资源功能(见 4.4 WebSocket 对话通道)。 - 用户uid参数,如有声书播放功能关联了用户uid,优先使用设备绑定的用户uid(见 9.3.1 绑定用户),系统默认赋值uid无需传参;如设备未绑定uid,WS 建连时必须传uid参数:
uid=xxx。
开播流程
- 媒体资源为 mp3 链接,端侧需流式播放
- 接收服务端开播事件和开播串场词后,等待串场词播放完成(串场词为正常交互 TTS,会先于开播事件下发),加载开播事件中的资源地址播放媒体资源
- 同时发送上行开播事件反馈给服务端
- 接收到开播事件后,开始执行心跳上行事件,直到服务端主动上报停播或客户端停播事件时停止
停播流程
- 服务端下发停播事件后,客户端结束媒体播放,上行停播事件,将当前播放进度等参数上行至服务端
- 资源自动播放结束时,上行停播事件(
progress=totalLength,finish=true),服务端自动判断:- 需要续播 → 下发新的开播事件(同开播)
- 有声书:切换到下一章节
- 音乐:切换到播放列表下一首
- 整本 / 整个列表完播 → 下发完播 TTS(同正常交互 TTS)
- 需要续播 → 下发新的开播事件(同开播)
播控
媒体资源开播时,支持输入播控事件:
| 播控操作 | 说明 |
|---|---|
| 暂停播放 / 上一集 / 下一集 / 重播 / 跳集 | 资源切换 |
| 点播 / 闲聊等事件 | 不支持(开播时无法进行) |
6.2.5 交互序列
先看端到端流程,再逐个对照事件字段(事件协议见 §6.2.6 上行 / §6.2.7 下行)。
序列一:开播
序列二:完播续播
序列三:播放中唤醒停止
服务端确保先推送串场词(TTS),后下发待播 URL(下行事件),端侧按此顺序处理。
6.2.6 协议:上行事件(端→云)
媒体资源事件 contentType 统一使用 AUDIO_BOOK(有声书与音乐共用)。
上行事件主体
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识符 |
| contentType | string | 是 | 固定 AUDIO_BOOK |
| content.eventType | string | 是 | 上行事件类型 |
| content.eventData | object | 是 | 事件数据 |
| t | long | 是 | 时间戳 |
AUDIO_BOOK_PLAY(开始播放)
端上开始播放媒体资源时发送。eventData 字段:bookId(当前播放资源 id,必填)+ chapterId(当前播放章节 id,必填)。
字段命名沿用
bookId/chapterId:
- 有声书:
bookId= 书 id,chapterId= 章节 id- 音乐:
bookId= 专辑 id(无专辑时与chapterId一致),chapterId= 歌曲 id
AUDIO_BOOK_PLAY 示例(点击展开)
json
{
"mid": "xxx",
"contentType": "AUDIO_BOOK",
"content": {
"eventType": "AUDIO_BOOK_PLAY",
"eventData": {
"bookId": "book_001",
"chapterId": "chapter_005"
}
}
}AUDIO_BOOK_STOP(停止播放)
媒体资源停止播放时必须发送该事件并提交当前播放进度;也可通过该事件主动停止:
- 播放中再次唤醒,退出播放状态进入对话状态
- 资源播放完成
eventData 字段:bookId(必填)+ chapterId(必填)+ progress(播放进度,已播长度秒,必填)+ finish(false 未完播 / true 完播,必填)。
AUDIO_BOOK_STOP 示例(点击展开)
json
{
"mid": "xxx",
"contentType": "AUDIO_BOOK",
"content": {
"eventType": "AUDIO_BOOK_STOP",
"eventData": {
"bookId": "book_001",
"chapterId": "chapter_005",
"progress": 120,
"finish": false
}
}
}资源自动播放结束时,
progress=totalLength,finish=true,触发服务端续播判断。
AUDIO_BOOK_PING(播放心跳)
⚠ 这是媒体资源播放心跳,与 WS 保活心跳(PING/PONG)是两个独立机制,不要混淆:
- WS 保活心跳(PING/PONG,30s 间隔):维持 WebSocket 连接,对话和媒体资源共用,见 4.3 §心跳与保活
- 媒体资源播放心跳(≤2s,本节):维持播放状态、上报进度,媒体资源特有
接收到开播事件后立即开始 ping/pong,直到服务端主动上报停播或客户端停播事件时停止。eventType 固定为 AUDIO_BOOK_PING,eventData 固定为 {}。
AUDIO_BOOK_PING 示例(点击展开)
json
{
"mid": "xxx",
"contentType": "AUDIO_BOOK",
"content": {
"eventType": "AUDIO_BOOK_PING",
"eventData": {}
}
}6.2.7 协议:下行事件(云→端)
下行事件主体
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | Integer | 是 | 响应状态码,200 成功,其他错误 |
| msg | string | 是 | 状态描述信息 |
| requestId | string | 是 | 请求唯一标识符 |
| mid | string | 是 | 对应上行请求唯一标识符 |
| t | long | 是 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 AUDIO_BOOK |
| content.roundId | string | 是 | 请求轮次 index |
| content.eventType | string | 是 | 事件类型 |
| content.eventData | object | 是 | 事件数据 |
AUDIO_BOOK_PLAY(下发播放资源)
播放媒体资源事件中会伴随播报 TTS,与正常语音交互相同,需要先播报 TTS 后再开始播放媒体资源(端上需将分开的 TTS 请求拼接下发)。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| bookId | string | 是 | 当前播放资源 id(有声书:书 id;音乐:专辑 id) |
| bookName | string | 是 | 当前资源名称(书名 / 专辑名 / 歌手名) |
| chapter | string | 是 | 当前播放章节名 / 歌曲名 |
| chapterId | string | 是 | 当前播放章节 id / 歌曲 id |
| chapterName | string | 是 | 当前播放章节名 / 歌曲名 |
| progress | long | 否 | 播放进度(已播长度) |
| totalLength | long | 是 | 音频总长(秒) |
| audioURL | string | 是 | 播放地址(mp3) |
| imageURL | string | 否 | 封面地址(有声书封面 / 专辑封面) |
端侧拿到
audioURL后流式播放,totalLength用于进度上报与续播判断。字段结构对有声书和音乐完全一致,端侧无需区分类型。
AUDIO_BOOK_STOP(下发停止)
停止播放事件中会伴随播报 TTS,与正常语音交互相同。停止播放后必须发送停止上行事件,同步播放进度,结束播放状态。eventData 仅含 bookId + chapterId(均必填)。
AUDIO_BOOK_PONG(心跳下行)
eventType 固定为 AUDIO_BOOK_PONG,eventData 固定为 {}。
AUDIO_BOOK_PONG 示例(点击展开)
json
{
"requestId": "0df8a585-7e5c-4464-8d90-d06557f4ea1d",
"mid": "xxx",
"contentType": "AUDIO_BOOK",
"content": {
"eventType": "AUDIO_BOOK_PONG",
"eventData": {}
}
}其他下行事件
媒体资源场景除上述开播 / 停播 / 心跳事件外,还会复用以下通用下行事件,完整字段见 附录 B.3:
| 事件 | 用途 |
|---|---|
TTS_SENTENCE_START / TTS / TTS_COMPLETE | 串场词 TTS 三事件联动(先 TTS 后播媒体资源) |
AGENT(contentType=AGENT) | 串场词明文,可当字幕(按序拼接 content.content,至 finishReason=stop) |
CALL_SKILL_EVENT | 指令事件 |
CALL_AGENT_INTERRUPTED | 打断事件 |
⚠ 判断有无串场词 TTS:用
TTS_SENTENCE_START事件判断。媒体资源场景一定有串场词 TTS,但为扩展性尽量统一用此事件。
事件速查
| 方向 | 事件 | 用途 |
|---|---|---|
| 上行 | AUDIO_BOOK_PLAY | 开始播放(上报资源 / 章节 id) |
| 上行 | AUDIO_BOOK_STOP | 停止播放(上报进度 + 完播标志) |
| 上行 | AUDIO_BOOK_PING | 播放心跳(≤2s,维持播放状态) |
| 下行 | AUDIO_BOOK_PLAY | 下发播放资源(audioURL + totalLength) |
| 下行 | AUDIO_BOOK_STOP | 下发停止(伴随停播 TTS) |
| 下行 | AUDIO_BOOK_PONG | 心跳下行 |
| 下行 | TTS_SENTENCE_START / TTS / TTS_COMPLETE | 串场词 TTS 三事件联动 |
| 下行 | CALL_SKILL_EVENT | 指令事件 |
| 下行 | CALL_AGENT_INTERRUPTED | 打断事件 |
下一步
三方内容资源对接:读 7.2 外部媒体资源接入 —— 资源检索 / 详情接口,多轮检索与续播机制
媒体资源排查:读 第9章 §9.4 有声书 / 内容类 —— 不播放 / 不停止 / 断续 / 串场词混乱
回看 WS 事件:读 4.4 WebSocket 对话通道 —— TTS / COMPLETE / 打断事件全集
服务端链路:读 4.6 服务端链路设计 —— ASR / Flow / TTS 三模块如何处理媒体资源播放
自定义技能与 A2A:读 7.1 外部智能体接入 —— 三方内容资源也可通过 A2A 流式输出
其他场景:读 6.1 指令与控制 / 6.3 魔法打印接入 / 6.4 视觉对话接入