0755-82922363

杰理AC791 AI对话 TTS音频下行链路分析


LLM 文本 → TTS 语音 → OPUS 编解码 → 播放:完整技术链路

1. 文档目标

系统讲清楚以下链路涉及的业务流程、技术原理、背景知识以及每个参数为什么这样选

LLM 文本 → TTS 语音合成 → OPUS 编码 → 网络传输 → OPUS 解码 → 扬声器播放

本文不涉及具体代码实现,只讲业务流、技术原理和参数设计。


2. 整体业务流全景

2.1 完整链路图
image.png

flowchart TD
%% 云端服务模块
subgraph 云端服务
A["用户语音 → STT 识别为文本"]
B["LLM 大语言模型生成回复文本"]
C["TTS 文本转语音引擎"]
D{"TTS 输出格式"}
D1["原始 PCM"]
D2["MP3 / WAV"]
D3["解码为 PCM"]
E["PCM 重采样 + 转单声道 + 按帧切分"]
F["OPUS 编码器压缩"]
end

%% 网络传输模块
subgraph 网络传输
G["JSON 控制消息:字幕/状态"]
H["二进制 OPUS 音频包"]
end

%% 设备端模块
subgraph 设备端
I["接收 JSON → 更新字幕和设备状态"]
J["接收 OPUS 包 → 放入解码队列"]
K["OPUS 解码 → 得到 PCM"]
L{"设备采样率 = 服务端采样率?"}
M["重采样适配"]
N["直接使用"]
O["PCM 送入播放队列"]
P["音频硬件驱动输出"]
Q["扬声器发声"]
end

%% 云端服务流程连线
A --> B 
B --> C 
C --> D
D -->|直接输出 PCM| D1 --> E
D -->|输出 MP3/WAV| D2 --> D3 --> E
E --> F
F --> H
B -.文本字幕.-> G

%% 网络传输 → 设备端流程连线
G --> I
H --> J 
J --> K 
K --> L
L -->|不一致| M --> O
L -->|一致| N --> O
O --> P 
P --> Q

2.2 核心要点

  • LLM 只负责生成文本,不产出任何音频
  • TTS 引擎在云端运行,把文本合成为语音
  • OPUS 编码在云端完成,设备端只做解码和播放
  • 设备同时收到两路数据:
    • JSON 文本消息:用于屏幕字幕显示、控制设备状态机
    • OPUS 二进制音频包:用于扬声器真正发声
  • 这两路是并行的,不是串行的

3. 每个环节的技术原理

3.1 LLM 大语言模型

输入:用户的语音识别结果(文本)

输出:自然语言回复(纯文本字符串),例如 "今天天气晴,最高温度 26 度。"

关键特性

  • LLM 是流式输出的,一边生成 token 一边往下游推送
  • TTS 不需要等整句话生成完才开始合成
  • 流式能力直接决定了整条链路的首包延迟(用户说完话到听到回复的等待时间)

3.2 TTS 文本转语音

做什么

把 LLM 输出的文本转换成人声语音波形。

常见 TTS 输出格式对比

格式本质特点
PCM未压缩原始采样体积大,无需解码,零延迟
WAVPCM + 文件头本质还是 PCM,多了 44 字节头
MP3有损压缩广泛兼容,但编码延迟大(~100ms+)
OGG/Opus低延迟有损压缩专为实时通信设计
AAC有损压缩苹果生态常用,需要授权费

为什么不直接把 TTS 原始输出发给设备

  • PCM/WAV 太大:16kHz/16bit/mono PCM,每秒 32KB,10 秒对话 320KB,对嵌入式设备和窄带网络负担沉重
  • MP3 延迟高:MP3 编码器帧延迟较大,不适合逐句流式场景
  • 需要统一格式:设备上行(麦克风)和下行(语音回复)需要统一协议,避免维护两套编解码器

结论:无论 TTS 引擎输出什么格式,都在云端统一转换为 OPUS 再发给设备。


3.3 OPUS 编解码器

背景

OPUS 是由 IETF 标准化的开放音频编码格式(RFC 6716),专为实时互联网通信设计。WebRTC、Discord、Zoom、微信语音通话等产品的底层都使用 OPUS。

OPUS vs 其他编码对比

特性OPUSMP3AACPCM
算法延迟2.5~60ms 可调~100ms+~20ms+0ms
码率范围6~510 kbps32~320 kbps8~256 kbps固定
语音专项优化✅ SILK 内核不适用
帧长灵活性2.5~120ms 多档固定 26ms固定 ~21ms任意
丢包容忍内置 FEC + PLC极差
流式友好天生流式需缓冲需缓冲天生流式
嵌入式适用复杂度可调(0~10)解码较重解码较重无需解码
开源免版税专利已到期❌ 需授权不适用

OPUS 的内部结构

OPUS 是两个编码器的混合体:

┌──────────────────────────────────────┐
│OPUS 编码器│
││
│┌──────────┐┌───────────────┐│
││ SILK││ CELT││
││(语音) ││(音乐/通用)││
│└──────────┘└───────────────┘│
│ ↑↑│
│窄带/宽带语音 全频带音频│
│(人声为主)(音乐/混合)│
└──────────────────────────────────────┘
  • SILK 内核:源自 Skype,针对人声优化,低码率下语音清晰度极佳
  • CELT 内核:源自 Xiph.org,针对全频带通用音频
  • OPUS 会根据输入内容自动切换或混合两个内核

为什么 OPUS 特别适合 AI 语音助手

  1. 低延迟:对话要求自然流畅,OPUS 算法延迟远低于 MP3
  2. 低码率音质好:16kbps OPUS 语音质量 ≈ 64kbps MP3
  3. 帧长可调:可根据嵌入式设备处理能力选择合适帧长
  4. 复杂度可调:嵌入式 MCU 可以把复杂度设到最低,省 CPU
  5. 天然流式:收到一帧解码一帧,不需要缓冲整段音频
  6. 上下行统一:麦克风上传和语音下发共用同一套编解码器

3.4 网络传输

并行双通道

设备和服务端之间同时维持两个逻辑通道:

通道内容作用
控制通道JSON 文本消息状态切换、字幕显示
音频通道OPUS 二进制包真正的语音数据

两种传输方案

方案 A:WebSocket 全双工

设备 ◄══════ WebSocket ══════► 服务端
文本帧 (JSON)◄─────►
二进制帧 (OPUS) ◄─────►
  • 一条连接承载 JSON + 音频
  • 基于 TCP,可靠传输
  • 实现简单,延迟略高

方案 B:MQTT 控制 + UDP 音频

设备 ◄── MQTT/TLS ──► 服务端(JSON 控制,可靠)
设备 ◄── UDP/AES ───► 服务端(OPUS 音频,低延迟)
  • 控制走 MQTT/TLS:可靠、有 QoS
  • 音频走 UDP + AES-128-CTR 加密:更低延迟
  • 需要自行处理丢包和序列号校验
  • 比 WebSocket 方案延迟更低,但实现更复杂

握手协商

设备连接时发送 hello 消息声明音频参数:

{"type": "hello","audio_params": {"format": "opus","sample_rate": 16000,"channels": 1,"frame_duration": 60}}

服务端回复确认最终参数(可能微调采样率等),双方协商一致后音频通道正式开启。

一次完整的 TTS 消息时序

时间 ─────────────────────────────────────────────────────►

 ① {"type":"tts", "state":"start"}设备进入"播放"状态
 ② {"type":"tts", "state":"sentence_start", 屏幕显示字幕
 "text":"今天天气晴"}
 ③ [OPUS包][OPUS包][OPUS包]... 扬声器播放这句话
 ④ {"type":"tts", "state":"sentence_start", 下一句字幕
 "text":"最高温度 26 度"}
 ⑤ [OPUS包][OPUS包][OPUS包]... 播放下一句
 ⑥ {"type":"tts", "state":"stop"} 设备回到"空闲/聆听"

文本消息和音频包是交替并行发送的,不是先发完所有文本再发音频。


3.5 设备端解码与播放

解码流程

OPUS 音频包到达
 │
 ▼
检查采样率和帧长 → 必要时重新配置解码器
 │
 ▼
OPUS 解码 → 得到 PCM(16bit 有符号整数)
 │
 ▼
采样率匹配检查
 │
 ├── 不一致 → 重采样适配硬件
 └── 一致 → 直接使用
 │
 ▼
送入播放队列
 │
 ▼
音频硬件驱动(I2S / Codec 芯片)
 │
 ▼
扬声器发声

为什么需要重采样

  • 服务端 TTS 可能输出 24kHz(高质量 TTS 常见)
  • 设备硬件 Codec 可能只支持 16kHz 或 48kHz
  • 重采样器作为兜底,让协议层保持灵活,不强绑固定采样率

三任务并行模型

设备端音频系统拆分为三个独立实时任务:

┌───────────────┐ ┌────────────────┐ ┌───────────────┐
│音频输入任务 │ │ 编解码任务│ │音频输出任务 │
│(最高优先级) │ │(中等优先级) │ │(较高优先级) │
│ │ ││ │ │
│麦克风采集│ │上行:│ │从播放队列取 │
│唤醒词检测│ │ PCM → OPUS │ │PCM 数据│
│语音前端处理 │ │下行:│ │写入音频硬件 │
│ │ │ OPUS → PCM │ │驱动扬声器│
└───────┬───────┘ └────────┬───────┘ └───────┬───────┘
│││
▼▼▼
编码队列 ──►解码/发送队列 ◄── 播放队列

为什么这样拆分

  • 音频输入 优先级最高:麦克风必须实时采集,否则丢帧
  • 编解码 单独任务:CPU 密集操作,不能阻塞 I/O
  • 音频输出 独立运行:保证播放连续平滑,不被解码或网络抖动打断

为什么队列里存 OPUS 包而不是 PCM

同一个 60ms 音频帧的大小对比:

格式大小
PCM(16kHz/16bit/mono)960 采样 × 2 字节 =1920 字节
OPUS 压缩后通常40~120 字节

OPUS 包体积约为 PCM 的 1/15 ~ 1/50。在只有几百 KB 可用 RAM 的 MCU 上:

  • 用更少内存缓冲更长时间的音频
  • 减少内存分配压力
  • 降低队列阻塞风险

3.6 本地提示音:另一条辅助链路

除了在线语音回复,设备还有本地提示音(如开机音、错误提示音)。

内置 OGG 音频资源(封装的也是 Opus)
 │
 ▼
OGG 解封装 → 提取出 Opus 帧
 │
 ▼
送入同一条解码队列
 │
 ▼
复用完全相同的 OPUS 解码 → 播放链

设计好处:在线语音和本地提示音共用同一套播放基础设施,不需要额外维护 MP3/WAV 解码器。


4. 参数选择详解

4.1 参数总览

参数类别
编码格式OPUS传输格式
采样率16000 Hz音频质量
通道数1(单声道)音频质量
帧长60 ms延迟与效率
码率自动(Auto)压缩策略
复杂度0(最低)CPU 负载
前向纠错 FEC关闭抗丢包
不连续传输 DTX开启省电省带宽
可变码率 VBR开启压缩效率
队列缓冲上限~2400 ms流畅度

4.2 采样率:16000 Hz

背景

采样率决定可表达的最高频率(奈奎斯特定理:最高频率 = 采样率 / 2)。

采样率最高频率典型用途
8000 Hz4 kHz电话语音(窄带)
16000 Hz8 kHz宽带语音、语音助手
24000 Hz12 kHz高质量 TTS
48000 Hz24 kHz专业音频/音乐

选择原因

  • 语音频带完整覆盖:人声基频 85~255 Hz,共振峰 300~3400 Hz,辅音能量到 ~8 kHz。16kHz 完整覆盖
  • 语音模型标准:绝大多数 STT / TTS 模型以 16kHz 为标准
  • 资源与质量甜点:比 8kHz 明显更清晰;比 24kHz/48kHz 节省一半以上带宽和处理量
  • 嵌入式友好:ESP32 级 MCU 处理 16kHz 游刃有余,48kHz 就需要更大缓冲和更多 CPU

每秒数据量对比

采样率每秒 PCM(16bit mono)每分钟
8 kHz16 KB960 KB
16 kHz32 KB1.9 MB
24 kHz48 KB2.8 MB
48 kHz96 KB5.6 MB

4.3 通道数:1(单声道)

  • 语音助手不需要空间定位:不像音乐需要立体声
  • 数据量减半:单声道 = 双声道的 50%
  • 编解码负载减半
  • 嵌入式设备通常单扬声器
  • 队列内存减半:对 RAM 紧张的 MCU 至关重要

4.4 帧长:60ms

背景

OPUS 支持的帧长:2.5 / 5 / 10 / 20 / 40 / 60 / 80 / 100 / 120 ms

帧长决定了每次编解码处理的音频时长、每个网络包的大小、端到端延迟的下限。

帧长的权衡

短帧 (5~20ms)长帧 (60~120ms)
 ◄──────────────────────────────────────────────►
 低延迟高延迟
 高包率(网络开销大)低包率(网络开销小)
 低压缩效率 高压缩效率
 高CPU中断频率 低CPU中断频率
 适合实时通话适合嵌入式/低功耗

选择 60ms 的原因

维度60ms 的表现
压缩效率帧内统计冗余多,压缩率比 20ms 更高
网络包率每秒 ~17 个包(vs 20ms 的 50 个包),减少包头开销
CPU 调度编解码每秒触发 ~17 次(vs 50 次),更省 CPU
队列管理同样缓冲区存放更长时间音频
延迟60ms 帧延迟 + 网络 + 处理 ≈ 150~300ms,对话场景可接受

帧长对帧大小的影响

60ms,16kHz,mono:

  • PCM 帧:16000 × 0.06 = 960 采样 × 2 字节 = 1920 字节
  • OPUS 帧:压缩后约 40~120 字节

队列缓冲设计

项目将队列缓冲上限设为 ~2400ms,即约 2400 / 60 = 40 个 OPUS 包。

这个设计保证:

  • 有足够缓冲应对网络抖动
  • 不会因为缓冲过多导致延迟过大
  • 内存占用可控(40 个 OPUS 包 ≈ 40 × 100 = 4KB,远小于 40 帧 PCM 的 77KB)

4.5 码率:自动(Auto)

什么是自动码率

让 OPUS 编码器根据当前帧的音频内容自动决定分配多少比特:

  • 安静段 → 低码率
  • 复杂语音段 → 高码率
  • 过渡段 → 中等码率

为什么不手动指定固定码率

  • 固定码率无法适应语音内容的动态变化
  • 指定过高浪费带宽,指定过低损害音质
  • 自动模式是 OPUS 官方推荐的语音场景默认值
  • 对于语音助手这种内容不可预测的场景,自动模式最稳妥

4.6 复杂度:0(最低)

背景

OPUS 的 complexity 参数范围 0~10,控制编码器搜索最优压缩方案的努力程度:

复杂度CPU 占用压缩效率适用场景
0最低稍低嵌入式设备
5中等较好普通手机/PC
10最高最优服务器端/离线处理

选择 0 的原因

  • 实时优先:MCU 必须在一帧时长(60ms)内完成编码,复杂度高可能超时
  • 低功耗:智能硬件长期在线运行,省 CPU = 省电
  • 可接受的质量差异:complexity 0 vs 10 在语音场景下的主观音质差异很小(OPUS 本身在语音上已经很好)
  • 只影响编码端:设备端上行编码用 0,服务端下行编码可以用更高值

4.7 前向纠错 FEC:关闭

什么是 FEC

Forward Error Correction,编码时在当前包中嵌入前一包的冗余信息。如果前一包丢失,解码器可以从当前包中恢复它。

开启 FEC 的代价

  • 码率增加约 50%
  • 编码计算量增加
  • 引入额外延迟

为什么关闭

  • WebSocket 方案基于 TCP:TCP 本身保证可靠传输,不会丢包
  • UDP 方案更依赖轻量低延迟:靠序列号检测丢包,接受偶尔丢帧,而不是增加冗余开销
  • 语音对话场景容忍偶尔丢帧:人耳对短暂(60ms)的语音缺失不太敏感,OPUS 解码器内置 PLC(包丢失隐藏)可以平滑过渡

4.8 不连续传输 DTX:开启

什么是 DTX

Discontinuous Transmission,当检测到输入是静音或背景噪声时,编码器停止发送或只发极小的静音描述包。

开启的好处

  • 省带宽:对话中大量时间是"无人说话"的静默段
  • 省电:不编码不发送 = CPU 空闲 + 无线模块休眠
  • 减轻服务端压力:无效音频不传输
  • 长期在线设备尤其受益:语音助手 90% 以上的时间处于待命/静音状态

注意事项

  • DTX 只影响上行(麦克风 → 服务端),下行 TTS 语音通常无大段静默
  • 恢复说话时有极短的首帧延迟(通常 <20ms),对对话体验无感知影响

4.9 可变码率 VBR:开启

什么是 VBR

Variable Bit Rate,每一帧根据内容复杂度动态分配不同的码率。

与 CBR(Constant Bit Rate,固定码率)对比:

模式特点
VBR安静段省码率,复杂段多给码率,整体更高效
CBR每帧码率固定,简单可预测,但压缩效率较低

选择 VBR 的原因

  • 语音的动态范围大:元音能量高,辅音能量低,静默无能量
  • VBR 能把码率花在刀刃上
  • OPUS 官方推荐语音场景使用 VBR
  • 配合 DTX,静默段几乎零码率

4.10 解码端重采样

为什么存在

服务端 TTS 输出的采样率和设备硬件 Codec 的工作采样率不一定相同。例如:

  • 服务端 TTS 输出 24kHz(高质量 TTS 常见)
  • 设备端 Codec 芯片运行在 16kHz

工作方式

  • 设备在握手阶段收到服务端确认的采样率
  • 如果与本机硬件采样率不一致,启动重采样器
  • 重采样在 OPUS 解码之后、写入硬件之前执行

设计好处

  • 协议层保持灵活,不硬编码某一个采样率
  • 板级硬件差异被隔离在最后一环
  • 未来服务端升级 TTS(如从 16kHz 升到 24kHz)不需要改设备固件

5. 上行链路:为什么也要了解

虽然主题是"文本到播放"(下行),但理解上行链路有助于理解参数为什么这样统一设计。

上行业务流

麦克风采集 → 语音前端处理(降噪/回声消除) → PCM 分帧 → OPUS 编码 → 网络发送 → 服务端 STT

上下行参数统一的好处

  • 协议统一:上下行用同一种音频格式,简化协议设计
  • 编解码器复用:设备只维护一套 OPUS 编解码器
  • 队列结构复用:帧长一致,队列管理逻辑通用
  • 内存可预测:统一帧大小,内存分配可预算
  • 服务端处理简化:收发都是 OPUS,无需多格式适配

6. MP3/WAV 与当前架构的关系

6.1 当前架构的真实情况

  • 在线音频协议声明的格式是 opus,不是 MP3 也不是 WAV
  • 设备端只包含 OPUS 编解码器,没有 MP3/WAV 解码器
  • 本地提示音也是 OGG(Opus) 封装,不是 MP3/WAV

结论:当前项目在线语音回复链路不涉及 MP3/WAV。

6.2 如果上游 TTS 输出 MP3/WAV 怎么办

推荐做法:在服务端完成转换

TTS 输出 MP3/WAV
 │
 ▼ (服务端)
解码为 PCM → 重采样到 16kHz/mono → 按 60ms 分帧 → OPUS 编码
 │
 ▼ (网络)
发给设备 → 设备端正常 OPUS 解码 → 播放

为什么不在设备端解码 MP3/WAV

因素服务端转换设备端解码
CPU 负载服务端资源充裕MCU 负担重
内存占用不影响设备需额外解码器内存
网络带宽OPUS 传输,带宽最优MP3/WAV 直传,带宽浪费
实时性OPUS 天生流式MP3 需要缓冲
维护成本设备端无需改动需新增解码器和适配
架构一致性保持统一引入异构路径

7. 完整参数速查表

参数选择原因
格式OPUS低延迟、低码率语音好、流式、免版税、嵌入式友好
采样率16kHz语音频带甜点、STT/TTS 标准、嵌入式可承受
通道Mono语音不需立体声、省一半资源
帧长60ms压缩效率与延迟的折中、嵌入式省 CPU 省内存
码率Auto自适应内容、OPUS 推荐默认值
复杂度0MCU 实时约束、省电、语音下音质差异小
FEC关闭TCP 已可靠、UDP 接受偶尔丢帧、省码率
DTX开启静默段省电省带宽、长期在线设备必备
VBR开启语音动态范围大、码率花在刀刃上
队列缓冲~2400ms抗网络抖动、不过度延迟、内存可控

8. 一句话总结

云端 LLM 生成文本 → 云端 TTS 合成语音 → 云端 OPUS 编码压缩 → 网络传输(JSON 字幕 + OPUS 音频并行)→ 设备端 OPUS 解码为 PCM → 必要时重采样 → 音频硬件驱动 → 扬声器发声。

全链路以 OPUS 16kHz/mono/60ms 为核心,在延迟、码率、音质、嵌入式资源之间取得最优平衡。


上一篇:
杰理AC791 AI对话 ASR音频上行链路分析
下一篇:
没有了!
联系方式

地址:深圳市龙华区观湖街道观乐路5号多彩科创园B栋801

邮箱:steven@yunthinker.com