主题
4.5 音频格式与分片
语音对话的底层是音频流。选对格式、正确分片,直接影响延迟与稳定性。
支持的音频格式
上行(设备 → 云端)
| 格式 | 说明 | 推荐度 |
|---|---|---|
| PCM | 原始音频,16k/16bit/单声道,无需压缩 | 默认 |
| Opus | 压缩格式,体积约 PCM 的 1/8,降低流量与弱网风险;支持 CBR/VBR | ⭐ 强烈推荐 |
| mp3 | 不支持上行 | — |
| 参数 | 取值 | 说明 |
|---|---|---|
| codec | pcm(默认) / opus(推荐,体积 1/8) | mp3 不支持上行 |
| sampleRate | 16000 | 默认 16k |
| PCM 单包 | ≤300ms | 16k/16bit/单声道 |
| Opus 单包 | ≤480 字节,帧长 ≤120ms(建议 60ms) | 多包拼接总时长 ≤300ms |
| 发送间隔 | =音频时长 | 均匀发送,否则延时异常 |
下行(云端 → 设备,TTS)
| 格式 | 说明 | 备注 |
|---|---|---|
| PCM | 默认帧长 60ms,可设 60~120ms | — |
| Opus | 默认 60ms,可选 10/20/40/60ms;支持 CBR/VBR,默认VBR | 下发 opus 裸流是单声道 |
| mp3 | 支持,但不支持流式 |
| 参数 | 取值 | 说明 |
|---|---|---|
| codec | pcm / opus / mp3 | mp3 不支持流式切分 |
| frameSizeMs | pcm 60-120ms / opus 10/20/40/60ms | 下行 TTS 帧长 |
| enableOpusCbr | true/false | opus CBR,默认 VBR |
| 二进制传输 | audio.binary=true | 上行 ws.send(bytes) 替代 AUDIO;下行 binary frame 替代 TTS |
⚠ 下行格式要与端上解码能力匹配:端上解码 opus 需要相应解码库;mp3 不支持流式,内存不够缓存会丢包。
采样率
基础标准:16k 采样率、16 位深、单声道。
分片规则
PCM 上行
- 单包时长 ≤300ms
- 计算示例:16000Hz × 2bytes × 0.12s = 3840 字节/帧(120ms)
Opus 上行
Opus 上行涉及三个层级概念,先对齐术语(设备端工程师可结合 附录D 理解原理):
| 层级 | 定义 |
|---|---|
| 数据包 | 一次 WebSocket 音频上传的 byte[](JoyInside 传输层产物) |
| opus 音频包 | opus 标准的包,以 TOC 字节开头(opus Packet) |
| opus 帧 | opus 音频包内的帧(opus Frame) |
数据包构成:单包模式下数据包 = 1 个 opus 音频包;拼包模式下数据包 = 多个 opus 音频包裸拼接成 1 个 byte[](服务端按 frameSize 等长切分还原)。
JoyInside 上行 opus 能力清单:
| 能力 | 值 | 说明 |
|---|---|---|
| 帧长 | 2.5/5/10/20/40/60ms | 建议 60ms |
| opus 音频包时长 | ≤120ms | opus 标准硬上限 |
| opus 音频包字节 | ≤480(JoyInside默认上限) | 超过需设 frameSize |
| frameSize 配置 | 一个 opus 音频包的字节数 | audio.input.frameSize配置 |
| 压缩比 | 8:1 建议(≈32kbps) | 最高 24:1,超过解码失败;详见 附录D |
| 码率模式 | CBR / VBR | 由端侧编码器设置 |
| 包封装(c 位) | 0 / 1 / 2 / 3 号包 | opus 标准全支持;详见 附录D |
| 上行模式 | 单包(推荐)/ 拼包(不推荐) | 单包 1:1;拼包为多个 opus 音频包裸拼接 |
下行 TTS 帧长
| 格式 | 默认帧长 | 设置参数 | 可选值 |
|---|---|---|---|
| PCM | 60ms | audio.output.frameSizeMs | 60~120ms |
| Opus | 60ms | audio.output.frameSizeMs | 10/20/40/60ms |
| mp3 | 不支持流式 | — | — |
二进制传输
通过 CLIENT_VOICE_CHAT_UPDATE 设置 audio.binary=true 开启。开启后上下行音频走 WebSocket binary frame,其他事件仍走 text 通道:
开启后:
- 上行音频用
ws.send(bytes)发送(替代 AUDIO 事件的 base64) - 下行 TTS 用 binary frame 接收(替代 TTS 事件的 audioBase64)
- 其他事件(ASR/AGENT/COMPLETE 等)仍走 text 通道
若上下行二进制策略不同,可单独设
audio.input.binary/audio.output.binary(设此字段时不设audio.binary)。完整字段见 附录 B.3.2 配置更新。
未开启但传 bytes:
json
{"code":400,"msg":"audio binary not support."}配置示例(CLIENT_VOICE_CHAT_UPDATE)
完整配置示例(点击展开)
json
{
"mid": "uuid",
"contentType": "EVENT",
"content": {
"eventType": "CLIENT_VOICE_CHAT_UPDATE",
"eventData": {
"audio": {
"binary": true,
"input": {
"codec": "pcm",
"sampleRate": "16000"
},
"output": {
"codec": "opus",
"enableOpusCbr": true,
"sampleRate": "16000",
"frameSizeMs": "40"
}
}
}
}
}关键字段:
| 字段 | 说明 |
|---|---|
| audio.binary | 上下行二进制总开关(true/false) |
| audio.input.codec / sampleRate | 上行编码(pcm/opus)/ 采样率(16k/24k/32k) |
| audio.input.frameSize | 一个 opus 音频包的字节数;仅拼包时传,单包不传。语义与易踩坑详见 附录D |
| audio.output.codec / sampleRate | 下行编码(pcm/opus/mp3)/ 采样率 |
| audio.output.frameSizeMs | 下行 TTS 帧长(pcm:60-120 / opus:10/20/40/60,默认 60) |
| audio.output.enableOpusCbr | 输出 opus 时是否 CBR(true/false,默认 false) |
⚠ CLIENT_VOICE_CHAT_UPDATE 每连接只发一次,否则对话被打断。详见 3.3 step3。
⚠ 一定要收到
SERVER_VOICE_CHAT_UPDATED(更新配置成功)事件才算配置生效。
下一步
- 服务端如何处理事件: 4.6 服务端链路设计(进阶阅读)
- 音频相关排查:10.2 设备不说话/答非所问类
- 数字音频基础(采样/量化/编码):附录 D