2026 年 8 月 19 日,Nari Labs(开源 TTS 模型 Dia 的团队,Dia 在 Hugging Face 下载量超 200 万)发了一篇技术长文,把 Qwen3-TTS 1.7B CustomVoice 的服务化指标推到了一个新位置:单张 NVIDIA H100 SXM 上,10 RPS 并发下首音延迟(TTFA)p95 低于 50ms,20 RPS 时仍保持在 100ms 以内,全程无播放断流。按 H100 时租 4.29 美元估算,满负荷下合成成本约 2 美元/百万字符——ElevenLabs V3 是 100 美元,Cartesia Sonic 3.5 是 49 美元且延迟更高。
更关键的是:实现和基准测试代码全部开源。这意味着「自建一个能打的实时语音合成服务」从「需要一支推理团队」变成了「一个后端工程师一个周末的事」。这篇文章拆解方案里真正值得学的五条思路,然后给出三条按资源分层的落地路线。
一、先搞清楚「实时 TTS」到底考什么
很多人测 TTS 只看「生成完一句要多久」,这在实时场景里是错的。Nari Labs 把实时性拆成四个指标,这套框架值得你直接抄走:
| 指标 | 含义 | 不达标的体感 |
|---|---|---|
| 可闻 TTFA | 从发请求到第一声可听见音频的时间 | 语音助手「反应慢半拍」 |
| 零断流(underrun) | 播放开始后缓冲不断粮 | 声音卡顿、破音 |
| 容量 | 前两条在 RPS 上升后仍成立 | 一上量就崩 |
| 输出可懂 | 合成语音必须可理解 | 快了但听不清 |
注意第一个指标的措辞是「可闻」——模型返回的第一段 PCM 里往往带几十毫秒的前导静音,它会被算进 TTFA,但用户什么都没听到。这个细节后面有大用。
他们还用泊松分布的开放回路流量(模拟真实请求到达)跑了五分钟压测,并用 Deepgram STT 回测合成音频的可懂度。这套方法论比「for 循环打 100 个请求取平均」严谨得多。
二、五条优化思路:两条白嫖,三条进阶
先看他们测的四个现有推理引擎在默认配置下的成绩(1 RPS):vLLM-Omni 的 p95 可闻 TTFA 是 278ms 且 100% 请求有断流,SGLang-Omni 1141ms,VoxServe 315ms,M* 1160ms。也就是说默认配置下没有一个能用。以下五条是他们做到 50ms 的关键,前两条你不需要换框架就能用:
1. 动态裁剪前导静音(白嫖,收益约 80ms)。 用短窗口 RMS 检测持续语音的起始点,把起始点之前的采样扔掉,其余音频正常流式下发。模型推理一点没变快,但用户感知到的 TTFA 直接降约 80ms。
2. 调帧累积参数(白嫖)。 引擎会攒够若干 codec 帧才解码出一块音频。首块用小 chunk 让声音尽快出来,后续 chunk 放大换批处理效率和播放余量。vLLM-Omni 里对应的参数是 codec_chunk_frames 和 codec_chunk_ramp,其他引擎有等价的 chunk/stride 控制。调优目标是一个「无断流前提下 TTFA 最低」的配置组合。
3. 三模块统一调度(进阶)。 Qwen3-TTS 是三段式架构:Talker 预测每帧第一个 codebook token,Code Predictor 补全其余 15 个,Codec 把 token 解码成波形。多数实现把 Talker 和 Code Predictor 绑在一起跑,Nari 的做法是把三个模块暴露为三个独立可调度任务,交给同一个调度器——还没出首音的请求拿最高优先级,已开播的请求只在临近播放死线时才变急,调度器以紧急请求为锚点、用兼容任务填满 batch。
4. 利用 Code Predictor 的规则结构(进阶)。 它每帧固定跑 15 步,上下文短且有界,于是可以预分配 KV cache、把整帧生成循环捕获为一个 CUDA graph,再配一个专门的 Triton attention kernel。
5. 状态缓存式 Codec(进阶)。 朴素实现每出新一块就重算全部历史帧,他们让每个请求缓存 Transformer 上下文和卷积状态,增量解码只处理新帧;首块用全量解码保 TTFA,之后切增量解码保吞吐。另外他们还为预定义 batch 尺寸捕获 CUDA graph、避免不必要的 CPU-GPU 同步、支持输入流式接入(上游 LLM 边出字,TTS 边合成,进一步压低语音 Agent 的端到端延迟)。
三、动手:按资源选一条路线
路线 A:没卡,先跑通产品——用托管 API。 阿里云百炼平台提供 Qwen3-TTS 系列的实时合成接口(如 qwen3-tts-vc-realtime 快照模型),支持流式输出和语气自适应。适合验证产品形态,不用管任何部署。接入前先在控制台确认计费与并发配额。
路线 B:有卡,自己部署——vLLM-Omni 或 VoxServe + 两条白嫖优化。 以 vLLM-Omni 为例,起服务后先别急着压测,把前导静音裁剪加上。一个最小可用的 Python 参考实现:
import numpy as np
def trim_leading_silence(pcm: np.ndarray, sample_rate=24000,
window_ms=10, threshold_ratio=0.02):
"""检测首个持续有声窗口,返回裁剪起点之后的音频。"""
win = int(sample_rate * window_ms / 1000)
threshold = threshold_ratio * np.iinfo(np.int16).max
for start in range(0, len(pcm) - win, win):
chunk = pcm[start:start + win].astype(np.float32)
if np.sqrt(np.mean(chunk ** 2)) > threshold:
return pcm[start:]
return pcm # 全静音则不裁剪,兜底
然后写一个 TTFA 实测脚本,边调 codec_chunk_frames/codec_chunk_ramp 边看数字变化:
import time, requests
def measure_ttfa(url, text, first_bytes=4096):
t0 = time.perf_counter()
with requests.post(url, json={"text": text}, stream=True) as r:
for chunk in r.iter_content(chunk_size=512):
if chunk:
got = len(chunk)
if got >= 0: # 首个非空块
return (time.perf_counter() - t0) * 1000
return None
# 注意:要测「可闻」TTFA,应在客户端同样做静音检测,
# 而不是只记录第一个网络包到达时间
压测时记住用泊松到达的流量模型,并盯 p95 而不是平均值——平均 40ms 配 p95 400ms 的服务,用户记住的是后者。
路线 C:要极致指标——直接用 Nari 开源实现。 他们的实现与基准代码已开源(博客里有仓库入口)。这是目前公开方案里唯一在 10 RPS 下守住 50ms p95 的。代价是你得接受它的工程复杂度和相对早期的代码状态,适合有推理工程能力的团队。
四、成本账与选型提醒
- 成本对比(每百万字符):Nari 自托管约 $2(满负荷、不含网络与运维开销)、Cartesia Sonic 3.5 约 $49、ElevenLabs V3 约 $100。
- H100 时租按 4.29 美元计,10 RPS 下每秒约产 630 字符。「满负荷」是理想值,实际利用率打折,成本按等比例上浮,预算时至少按 50% 利用率估。
- 如果只是做语音助手 demo 或低频场景,路线 A 的托管 API 综合成本很可能低于养一张 H100——卡的时租是 7x24 小时计费的,不管你有没有请求。
- Qwen3-TTS 是 Apache 2.0 许可、支持 10 种语言、3 秒参考音频即可克隆音色,合规和商用空间都比较友好;但语音克隆功能上线前务必处理授权与合规问题,别拿别人的声音乱克隆。
小结
Nari Labs 这次的价值不只是「把 Qwen3-TTS 跑快了」,而是把实时 TTS 服务化的方法论摊开了:四个指标的定义、前导静音裁剪和帧累积调优这两个零成本优化、三模块统一调度的架构思路、以及一套严谨的开源基准。对多数团队来说,务实的路径是:先用托管 API 验证产品,量上来之后用 vLLM-Omni/VoxServe 加两条白嫖优化自部署,真正卡到延迟瓶颈再考虑 Nari 的完整方案。实时语音 Agent 的成本地板又被踩低了一截,接下来拼的就是谁先把体验做顺了。
