Skip to content

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 播报、资源播放、心跳保活、播控响应五个环节,端侧按下图顺序推进接入:

注意事项

  1. 在接入播控事件前,必须先接入媒体资源心跳事件(AUDIO_BOOK_PING / AUDIO_BOOK_PONG。服务端依赖心跳判定端侧真实播放状态,心跳最大间隔时间为2s;若心跳缺失,播控指令(暂停 / 上一集 / 下一集等)在服务端会被判定为「非播放态」,从而按点播 / 闲聊语义处理,导致播控失效。
  2. 建议遵守「先 TTS 串场词,后播媒体资源」的顺序。服务端会先下发串场词 TTS(TTS_SENTENCE_START / TTS / TTS_COMPLETE),再下发 AUDIO_BOOK_PLAY;端侧必须等串场词播放完成后再拉起 mp3 流式播放,否则会出现串场词与有声书 / 音乐叠音、或串场词被截断的问题。
  3. 停播事件(AUDIO_BOOK_STOP 上行)必须携带真实播放进度progress 单位为秒,finish 标识是否完播)。无论是资源自然播完、用户唤醒中断、还是服务端下发停止,端侧都必须上报,否则会导致续播定位错误、历史进度丢失、续播资源无法命中。

6.2.4 端侧接入概览

建连增加参数

  1. WS 连接时增加参数 feature=AUDIO_BOOK_V2 表示开启媒体资源功能(见 4.4 WebSocket 对话通道)。
  2. 用户uid参数,如有声书播放功能关联了用户uid,优先使用设备绑定的用户uid(见 9.3.1 绑定用户),系统默认赋值uid无需传参;如设备未绑定uid,WS 建连时必须传uid参数:uid=xxx

开播流程

  1. 媒体资源为 mp3 链接,端侧需流式播放
  2. 接收服务端开播事件和开播串场词后,等待串场词播放完成(串场词为正常交互 TTS,会先于开播事件下发),加载开播事件中的资源地址播放媒体资源
  3. 同时发送上行开播事件反馈给服务端
  4. 接收到开播事件后,开始执行心跳上行事件,直到服务端主动上报停播或客户端停播事件时停止

停播流程

  • 服务端下发停播事件后,客户端结束媒体播放,上行停播事件,将当前播放进度等参数上行至服务端
  • 资源自动播放结束时,上行停播事件(progress=totalLength, finish=true),服务端自动判断:
    • 需要续播 → 下发新的开播事件(同开播)
      • 有声书:切换到下一章节
      • 音乐:切换到播放列表下一首
    • 整本 / 整个列表完播 → 下发完播 TTS(同正常交互 TTS)

播控

媒体资源开播时,支持输入播控事件:

播控操作说明
暂停播放 / 上一集 / 下一集 / 重播 / 跳集资源切换
点播 / 闲聊等事件不支持(开播时无法进行)

6.2.5 交互序列

先看端到端流程,再逐个对照事件字段(事件协议见 §6.2.6 上行 / §6.2.7 下行)。

序列一:开播

序列二:完播续播

序列三:播放中唤醒停止

服务端确保先推送串场词(TTS),后下发待播 URL(下行事件),端侧按此顺序处理。

6.2.6 协议:上行事件(端→云)

媒体资源事件 contentType 统一使用 AUDIO_BOOK(有声书与音乐共用)。

上行事件主体

字段类型必选说明
midstring消息唯一标识符
contentTypestring固定 AUDIO_BOOK
content.eventTypestring上行事件类型
content.eventDataobject事件数据
tlong时间戳

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(播放进度,已播长度秒,必填)+ finishfalse 未完播 / 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_PINGeventData 固定为 {}

AUDIO_BOOK_PING 示例(点击展开)
json
{
  "mid": "xxx",
  "contentType": "AUDIO_BOOK",
  "content": {
    "eventType": "AUDIO_BOOK_PING",
    "eventData": {}
  }
}

6.2.7 协议:下行事件(云→端)

下行事件主体

字段类型必选说明
codeInteger响应状态码,200 成功,其他错误
msgstring状态描述信息
requestIdstring请求唯一标识符
midstring对应上行请求唯一标识符
tlong服务端处理时间戳(毫秒)
contentTypestring固定 AUDIO_BOOK
content.roundIdstring请求轮次 index
content.eventTypestring事件类型
content.eventDataobject事件数据

AUDIO_BOOK_PLAY(下发播放资源)

播放媒体资源事件中会伴随播报 TTS,与正常语音交互相同,需要先播报 TTS 后再开始播放媒体资源(端上需将分开的 TTS 请求拼接下发)。

字段类型必选说明
bookIdstring当前播放资源 id(有声书:书 id;音乐:专辑 id)
bookNamestring当前资源名称(书名 / 专辑名 / 歌手名)
chapterstring当前播放章节名 / 歌曲名
chapterIdstring当前播放章节 id / 歌曲 id
chapterNamestring当前播放章节名 / 歌曲名
progresslong播放进度(已播长度)
totalLengthlong音频总长(秒)
audioURLstring播放地址(mp3)
imageURLstring封面地址(有声书封面 / 专辑封面)

端侧拿到 audioURL 后流式播放,totalLength 用于进度上报与续播判断。字段结构对有声书和音乐完全一致,端侧无需区分类型。

AUDIO_BOOK_STOP(下发停止)

停止播放事件中会伴随播报 TTS,与正常语音交互相同。停止播放后必须发送停止上行事件,同步播放进度,结束播放状态。eventData 仅含 bookId + chapterId(均必填)。

AUDIO_BOOK_PONG(心跳下行)

eventType 固定为 AUDIO_BOOK_PONGeventData 固定为 {}

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 后播媒体资源)
AGENTcontentType=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打断事件

下一步