流式 TTS:把首包延迟压到 150ms

合成一句 12 个字的话,模型跑完要 1.2 秒。但如果做对了,用户感受到的延迟是 150ms。 这不是魔法,是流式 TTS 的基本盘。差别在于:你是等整句音频生成完再播,还是第一个音频块一出来就往用户耳朵里塞。前者用户等 1.2 秒,后者等 150ms——同一个模型,同样的算力,体验差一个数量级。 我在《实时语音对话的延迟预算》里把整条语音 Agent 链路拆过一遍,TTS 那一段只给了一句话:“要流式,首包出来就播。“这篇把那一句话展开,只讲 TTS。 为什么是"首包”,不是"整句” 先说清楚一个被混淆得很厉害的指标。 很多 TTS 厂商的官网首页挂着"实时率 0.3"或者"合成速度比真人快 3 倍"——这说的是整句合成耗时:一句 5 秒的话,1.5 秒合成完。这个数字对离线场景(把一本书转成有声书)有意义,对实时对话几乎没意义。 实时对话里真正决定体验的是 TTFA(time-to-first-audio,首包音频延迟):从你把文字喂给 TTS,到第一段能播放的音频抵达用户、开始出声,中间隔了多久。 道理和流式 LLM 一样。LLM 看的是首 token 延迟(TTFT),不是整段生成完的时间;TTS 看的是首包,不是整句。因为一旦第一个音节开始播,后面的音频是边合成边播的——只要合成速度比播放速度快(实时率小于 1),用户就永远听不到"卡壳"。整句要 1.5 秒还是 3 秒,用户根本感知不到,他在听前半句的时候,后半句已经悄悄合成好排在缓冲区里了。 所以这篇标题里的"150ms",指的是 TTFA。这是 2026 年一个够格但不极致的数字:对话不会让人觉得"AI 在想",但还没到 Cartesia Sonic-3 那种 40ms 模型延迟的极限。 有个数字陷阱要先点破。厂商宣传的"75ms"或"100ms"通常是纯模型推理时间——在一块独占 GPU 上,喂一段短文本,模型吐出第一块音频要多久。它不含网络往返、不含 API 网关排队、不含音频编码、不含你播放器的缓冲。一个 benchmark 跑 100ms 的模型,部署在共享云上、赶上流量高峰,端到端能轻松飙到 800ms。所以看 TTFA 数字,永远要问一句:这是模型延迟,还是用户真实感知到出声的延迟?这篇说的 150ms,是后者。 首包延迟花在哪 把 TTFA 拆开,大致是这么几块: ...

2026-05-13 · 2 min · Chico

语音合成的情绪与韵律:怎么让 AI 不像念稿

把同一句话放给两套 TTS 念:“你说得对,这个我之前还真没想到。” 两套都咬字清楚、没有杂音、采样率拉满。但其中一套你一听就知道是机器——不是因为它念错了,恰恰是因为它念得太"齐"了。每个字的时长几乎一样,每个停顿都卡在标点上,整句话像被一把尺子量过。 人不是这么说话的。人说"还真没想到"的时候,“真"会拖长一点,“没"会轻一点,“想到"前面会有个几乎听不见的迟疑。这些东西加起来,就是韵律(prosody)。发音准是 2020 年就解决的问题;韵律和情绪,才是 2026 年还在啃的硬骨头。 这篇讲清楚:念稿感到底差在哪儿,以及现在有哪几条路去补。 念稿感不是发音问题,是韵律问题 先把概念拆开。一段语音里,“说了什么"是文本内容,“怎么说的"是韵律。韵律不是一个东西,是四样东西叠在一起: 节奏(timing)——每个音、每个词占多长时间,语速是匀的还是有快有慢。 停顿(pause)——停在哪里,停多久。停顿不只在逗号句号,也在一个意群说完、或者你要强调下一个词之前。 重音(stress)——哪个词被加重了。”我没说过"和"我没说过”,意思完全不同。 语调(intonation)——句子的音高曲线。陈述句往下走,疑问句往上挑,反问句又是另一条线。 念稿感的根源,是早期 TTS 把这四样都做成了"默认值”:语速恒定、停顿只认标点、不分轻重、语调按句型套模板。结果就是每句话都念得四平八稳,像新闻联播里的提示音。 更麻烦的是,韵律和情绪是强耦合的。同样一句"你来啦”,高兴时音高整体偏高、句尾上扬;敷衍时又平又短;惊讶时第一个字猛地拔高再回落。情绪不是在准确的发音上再"刷一层颜色”,情绪本身就是通过韵律表达出来的。所以"TTS 加情感"这件事,本质上是"让 TTS 学会控制韵律"。 学术界很早就指出了拦路的三个问题:标签依赖(模型只会照训练时见过的"高兴/悲伤"几个标签走)、风格纠缠(想让它变开心,音色也跟着变了)、控制粒度太粗(只能整句一个情绪,改不了某个词)。这三条到现在也没完全解决,只是被绕过的方式越来越多。 控制韵律的四条路 2026 年要给语音"调情绪",大致有四种手段,从"最可控"到"最自然"排开,正好是个谱系。 flowchart LR A[SSML / 标记精确·机械] --> B[参考音频自然·难复用] B --> C[指令式控制灵活·偏意会] C --> D[上下文感知省心·难调试] style A fill:#fde7c2,stroke:#e8b23c style D fill:#cde9d6,stroke:#3c9e6a 第一条:SSML 和标记。 这是最老、也最确定的办法。你用标记语言显式地告诉引擎:这里停 300 毫秒、这个词音高升 10%、这段语速放慢。SSML 至今仍是工业界控制语音合成的事实标准,因为它可复现——同样的标记,出来的语音每次都一样。它的代价也明显:你得手动标,标多了维护成本极高,而且本质上是在用规则逼近一个连续的东西,生硬的接缝藏不住。新一代模型在 SSML 之外加了实验性的情绪标签,比如在句首写 [surprised],让整句带上惊讶的底色——比纯 SSML 省事,但仍然是离散的、一句一个。 第二条:参考音频。 不告诉模型"要开心",而是直接丢给它一段开心的录音,让它"照着这个感觉说"。Qwen3-TTS 这类模型 3 秒参考音频就能克隆音色和说话风格,Fish Audio S2 用 10 秒参考做跨语种迁移。这条路的好处是自然——韵律是从真人录音里"抄"来的,不是算出来的。坏处是难复用:你想要一个"略带歉意但又不卑微"的语气,得真去找到或录一段这样的音频,而且参考音频里的情绪和音色经常分不干净。 第三条:指令式控制。 用自然语言描述你要的效果:“用安慰的语气,慢一点,句尾别上扬。“这是 LLM 时代才成立的玩法。它灵活到几乎没有边界,你能描述出任何细微的语气。但它也最"意会”——同一句指令,不同模型、甚至同一模型不同时候,理解都可能有偏差。它适合创作和探索,不适合需要每次结果一致的生产链路。 ...

2026-04-26 · 2 min · Chico