深入讲解流式文本转语音的工程要点:音频分块传输、播放先于合成完成、LLM到语音层的连接方式、并发处理以及缓存策略,帮助开发者评估实时语音基础设施。
大多数开发者最初接触文本转语音时,它只是一个简单的请求-响应操作:
接收一个音频文件。
对于短提示词、旁白、通知或任何可以提前生成的内容来说,这种模式完全合理。
但当你去构建对话式 AI、实时 IVR、语音助手或其他动态生成输出的系统时,这种模式就会变得非常明显。
在这些应用中,用户等待的不是"音频生成",而是感受着沉默。
这就是流式 TTS 至关重要的原因。
流式管道不再等待整个响应合成完毕,而是在合成仍在进行时就开始交付音频。播放可以在响应的最后部分生成之前就开始。
对于开发者来说,有趣的不仅仅是流式传输更快。它改变了延迟的出现位置、音频缓冲方式、LLM 与语音层的连接方式、并发处理方式,以及缓存在何时仍然优于流式传输。
如果你正在评估实时语音基础设施,Smallest AI 是一个面向这类工作负载暴露 TTS 的平台示例。
根据 Global Market Insights 的数据,全球文本转语音市场 2025 年估值 48 亿美元,预计 2026 年将达到 57 亿美元。越来越多的应用正在加入生成式语音,但实时系统与离线语音生成有着截然不同的架构要求。
流式文本转语音的实际含义
传统的批量 TTS 采用完整的请求-响应周期运作。
你将完整文本发送到合成服务。服务生成完整的音频输出。直到那时,应用才会收到可以播放的内容。
Text
|
v
TTS synthesis
|
v
Complete audio
|
v
Playback
流式传输改变了交付模型:
Text
|
v
TTS synthesis
|
+--> Audio chunk 1 --> Playback starts
|
+--> Audio chunk 2
|
+--> Audio chunk 3
|
+--> ...
客户端不再等待合成完成后才执行有用的工作。
根据 API 的不同,流式传输可以通过以下机制实现:
HTTP 流式响应
提供商特定的实时协议
还有两个经常被归为"流式 TTS"的不同问题。
第一个是流式音频输出。你已经拥有完整文本,但 TTS 服务在合成结束前就开始返回已生成的音频。
第二个是流式文本输入和音频输出。输入本身仍在生成中(通常由 LLM 生成),TTS 管道在 LLM 响应完全存在之前就开始合成。
第二种情况对对话式 AI 尤为重要。
流式 TTS 不等同于低延迟 TTS
这个区别很容易被忽略。
低延迟批量 TTS 服务可能快速合成短响应并返回完整音频文件。
流式服务可能需要更长时间完成整个合成,但会更早开始返回可播放的音频。
对于交互式应用,这是不同的性能特征。
你应该通常测量至少以下指标:
首音频时间,用户在听到任何内容之前等待了多久
总合成延迟,完整生成需要多长时间
实时因子,音频生成速度是否快于消费速度
播放欠载,播放追上生成的速度有多频繁
尾部延迟,较慢请求的表现如何,而不仅仅是平均值
并发下的延迟,当许多会话同时运行时性能是否变化
对于对话系统,首音频时间通常比生成最终字节所需时间对感知响应度的影响更大。
这就是 Smallest AI 的文本转语音产品专注于实时语音生成以及传统 TTS 工作负载的原因之一。
为什么感知延迟才是真正的 UX 问题
人类对话在回合之间几乎没有死空间。
几百毫秒的停顿可能感觉完全自然。然而,一旦额外的处理层开始堆积,体验就会明显变得不那么对话式。
典型的语音管道可能已经包含:
用户说完话
|
v
语音识别完成
|
v
应用 / LLM 生成响应
|
v
TTS 开始合成
|
v
网络传输
|
v
客户端播放开始
TTS 只是延迟预算的一个组成部分。
如果每个阶段都等待前一阶段完全结束,延迟就会累积。
流式传输让你可以重叠工作。
例如,当 TTS 合成更早的句子时,LLM 可以继续生成文本。客户端可以播放那个句子,而下一个音频块仍在生成中。
LLM 完成
|
v
TTS 完成
|
v
播放
你得到的是更接近这样的结果:
LLM tokens ------->
sentence 1
|
v
TTS chunk 1 --------> playback
sentence 2
|
v
TTS chunk 2 -------->
sentence 3
|
v
TTS chunk 3 -------->
这种重叠是感知延迟改善的主要来源。
音频格式很重要,但流式传输不是编解码器功能
流式传输有时被解释为只有特定音频格式才能流式传输。
实际情况更为细致。
原始 PCM 对延迟敏感的管道很有吸引力,因为它几乎没有解码或容器开销。Opus 也常用于实时通信,因为它提供高效压缩并专为交互式音频设计。
MP3 和 AAC 在适当的流式配置中也可以渐进式交付。权衡在于,容器分帧、解码支持、缓冲行为和浏览器兼容性可能使它们在某些超低延迟管道中不那么方便。
正确的问题不仅仅是:
"这个格式支持流式传输吗?"
解码器能多快地消费第一批接收到的字节?
每个块是否包含足够的分帧信息?
你的播放环境是否支持该编解码器?
解码需要多少 CPU?
该格式节省多少带宽?
你的目标是浏览器、电话、移动设备还是原生应用?
对于通过电话运行的语音智能体,8 kHz 电话格式可能比高保真音频更有用。
对于浏览器应用,编解码器和播放 API 支持可能成为限制因素。
架构应该遵循最终的收听环境。
成本方程不仅仅是 API 定价
流式传输和批量合成在模型层的定价通常相似。
如果 API 按字符或生成用量收费,流式传输响应并不一定会使合成本身更便宜。
基础设施差异出现在其他地方。
使用批量实现时,你的服务可能在转发之前接收完整的音频负载。
这意味着更大的临时缓冲区,尤其是输出较长时。
流式实现可以在音频到达时转发较小的片段。
在高并发下,减少应用内存中保存的音频量可能很重要。
连接管理
流式传输并不能神奇地消除连接成本。
事实上,流式传输系统经常在音频生成或消费时保持 HTTP 或 WebSocket 连接活跃。
这将部分容量规划转向:
并发连接
负载均衡器超时
区域网络延迟
这正是批量合成可以决定性胜出的地方。
假设你的应用反复说:
Your payment was successful.
没有理由为每个请求都合成这个句子。
生成一次,缓存起来,然后提供现有音频。
当输出足够动态以至于缓存几乎没有收益时,流式传输最有价值。
如果你想要基于基准的延迟和生产级 TTS 评估的更广泛视角,Smallest AI 的快速文本转语音 API 指南涵盖了开发者应该比较的指标。
流式 TTS 何时是正确的架构
当文本在运行时才存在且用户正在等待响应时,流式传输是非常合适的选择。
典型例子包括:
对话式 AI 智能体
LLM 驱动的语音助手
开放式 IVR 系统
实时客户支持自动化
交互式无障碍应用
动态导航提示
根据用户上下文变化的语音应用
共同模式是交互性。
有用的输出开始得越快,系统感觉就越灵敏。

批量 TTS 何时仍然是更好的选择
流式传输并不是批量合成的通用替代品。
在以下情况下,批量通常是更简单的架构:
音频可以提前生成
相同输出将被反复播放
总渲染时间比首次音频时间更重要
你在离线创建播客或有声书
持久流连接增加了不必要的复杂性
激进的缓存可以消除重复合成成本
例如,50 个固定 IVR 菜单提示不应该为每个呼叫者实时合成。
同一 IVR 内的动态回答可能受益于流式传输。
生产系统通常同时使用两者。
如何将 LLM 连接到流式 TTS
一个常见的实时管道如下:
User speech
|
v
Speech recognition
|
v
LLM token stream
|
v
Text buffering
|
v
Sentence / phrase boundary
|
v
Streaming TTS
|
v
Audio queue
|
v
Playback
重要的一步是 LLM 和 TTS 之间的缓冲区。
将每个单独的 token 直接发送到合成通常并不理想。
想象一个 LLM 产生:
The
weather
tomorrow
will
be
warmer
than
today.
独立合成每个 token 会破坏自然的短语划分。
相反,应该积累足够的文本来创建一个有意义的语音单元:
The weather tomorrow will be warmer than today.
然后在 LLM 继续生成下一部分答案的同时,将该单元发送到 TTS。
句子边界是延迟-质量的权衡
等待完整的段落为 TTS 模型提供更多语言上下文,但会增加延迟。
发送很小的片段减少了等待时间,但可能损害韵律。
理想的块大小取决于:
TTS API 是否在块之间保持上下文
一个简单的实现可能在遇到以下情况时刷新文本缓冲区:
足够长的逗号分隔短语
但仅靠标点符号并不完美。
Dr. Patel will arrive at 4:30 p.m. tomorrow.
天真的分割可能产生糟糕的边界。
生产系统通常需要理解缩写、数字、域名和正在合成的语言的句子分割。
关键是同时测量延迟和听觉质量,而不是孤立地优化其中一个。
流式传输完整文本和流式传输 LLM 输出是不同的场景
对于使用 Smallest AI 语音层的开发者,当前的流式接口区分这些模式。
当你已有完整文本时,基于 SSE 的请求可以在合成进行时返回音频块。
当文本本身逐步到达时,例如 LLM token 流,持久 WebSocket 是更自然的架构。
这种区别很重要,因为应用程序控制在每种情况下不同形式的背压。
Full text -> TTS -> streamed audio
LLM -> text chunks -> TTS connection -> audio chunks
在第二种设计中,你的应用程序必须决定文本片段何时准备好合成。
创建并存储 API 密钥
将 API 密钥保存在环境变量中,而不是硬编码到应用程序中。
在运行代码片段之前,在仪表板中创建一个 Smallest.ai API 密钥,并将其存储在 SMALLEST_API_KEY 环境变量中。
export SMALLEST_API_KEY="your-api-key-here"
每个经过身份验证的请求都通过 Authorization 头发送该值:
Authorization: Bearer <SMALLEST_API_KEY value>
将密钥保存在你的服务器上。
不要将其暴露在浏览器 JavaScript、移动应用程序代码、公共仓库、屏幕截图、查询参数、客户端日志或返回给用户的错误消息中。
对于生产系统,使用托管服务商的密钥管理系统或其他适当的服务器端密钥管理器来存储密钥,而不是将其提交到配置文件。
使用 cURL 测试流式 TTS
以下示例发送完整文本并从 TTS 端点接收流式音频事件。
在运行代码片段之前,在仪表板中创建一个 Smallest.ai API 密钥,并将其存储在 SMALLEST_API_KEY 环境变量中。
curl --fail-with-body --show-error -N \
-X POST "https://api.smallest.ai/waves/v1/tts/live" \
-H "Authorization: Bearer $SMALLEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Streaming this paragraph chunk by chunk so playback can start sooner.",
"voice_id": "magnus",
"sample_rate": 24000,
"output_format": "pcm"
}'
从架构角度来看,重要的不是 cURL 命令本身。
而是响应可以被增量消费,而不需要等待完整的音频文件生成。
对于实际应用程序,你的服务器会解析流、解码音频负载,并将适当的音频数据转发到客户端或电话层。
Smallest AI 开发者平台是创建凭证并开始用你自己的工作负载测试语音层的地方。
客户端播放需要自己的缓冲区
快速接收音频并不能保证流畅播放。
网络是不稳定的。
想象服务器在这些时刻生成块:
chunk 1 100 ms
chunk 2 190 ms
chunk 3 270 ms
chunk 4 610 ms
chunk 5 690 ms
如果客户端在到达时立即播放所有内容,chunk 4 之前的延迟可能会产生可听见的间隙。
这就是为什么实时播放通常维护一个小抖动缓冲区或播放缓冲区。
缓冲区为系统提供足够的余量来吸收短期网络中断。
更低的延迟
更高的下溢风险
更高的稳定性
更高的感知延迟
没有通用的正确大小。
在你用户实际体验的网络条件下测量它。
浏览器播放注意事项
浏览器为你提供了几种可能的音频路径。
Web Audio API 为应用程序提供了对音频处理和调度的详细控制。
当你选择的媒体格式和浏览器支持符合 MediaSource 模型时,Media Source API 很有用。
对于原始 PCM,许多应用程序维护自己的队列并通过 Web Audio 调度解码的音频缓冲区。
你的客户端逻辑需要处理:
对于浏览器应用程序,经过身份验证的 TTS 请求仍然应该由你的服务器发出。不要仅仅因为播放组件生活在浏览器中就将你的提供商 API 密钥发送到浏览器。
Browser
|
| authenticated application request
v
Your server
|
| provider API credential
v
TTS API
|
| streamed audio
v
Your server
|
v
Browser playback queue
一旦所有内容都在流式传输,背压就变得重要
流式传输使管道更快,部分原因是各阶段可以并发运行。
它也引入了一个新问题。
当一个阶段比下一个阶段更快时会发生什么?
假设 LLM 生成文本的速度比 TTS 合成的速度快得多。
LLM
|
v
[text][text][text][text][text][text]
|
v
TTS
现在你增加了内存使用量,并可能创建了用户尚未听到的若干秒语音。
这使得中断变得困难。
如果用户在五个句子已经排队等待语音时改变方向,系统可能需要丢弃那些工作。
生产流式架构应该定义:
取消语义
已生成但未播放的音频是否应该被丢弃
流式传输不仅是为了更快地移动字节。它还关乎控制并发发生的工作。
打断(Barge-in)再次改变了设计
对话式语音应用程序通常允许用户打断助手。
这意味着你的系统可能需要取消:
当前正在播放的音频
已生成但尚未播放的音频
仍在合成的 TTS 请求
仍在生成的 LLM token
如果没有协调取消,应用程序可能在本地停止播放,而服务器继续生成没人会使用的内容。
取消路径应该被视为正常架构的一部分,而不是边缘情况。
一个有用的心智模型是:
User interruption
|
+--> stop playback
|
+--> clear audio queue
|
+--> cancel TTS generation
|
+--> cancel or redirect LLM generation
|
+--> begin listening again
这是高度交互式语音应用程序中 WebSocket 导向管道常见的原因之一。
当文本被分块时,SSML 变得更加复杂
语音合成标记语言(SSML)规范为发音、停顿、速率、音高和重音等提供了控制。
在批量合成中,TTS 系统可以在生成语音之前检查完整的 SSML 文档。
流式传输使这变得更难。
一个块可能包含:
<prosody rate="slow">
而关闭标签稍后到达。
这是否有效取决于实现。
不要假设提供商的批量 SSML 行为与其流式行为相同。
如果 SSML 对你的应用程序很重要,请测试:
跨块边界延伸的标签
发音词典
无效的部分标记
在带标记文本中间的取消
跨块的语音一致性需要测试
神经语音生成高度依赖上下文。
孤立合成的句子与作为段落一部分合成的同一句子,听起来可能并不完全相同。
因此,过度激进地拆分响应可能会导致:
重复的语调模式
不同的情感表达
片段之间的可听边界
这是不要将最小可能的文本块视为最佳文本块的另一个原因。
你正在优化的是一个多维系统:
延迟
质量
稳定性
成本
可中断性
最佳生产设置通常是权衡的结果。
流式传输并不会减轻你对流经系统的数据的责任
流式传输并不会减少你对数据流的责任。对于处理敏感信息的应用程序,需要记录:
输入文本的来源
哪个服务接收它
请求是否被记录
音频是否被保留
流量如何加密
临时缓冲区存活多长时间
哪些区域处理数据
重试期间会发生什么
哪些系统可以访问生成的音频
对于包含电子受保护健康信息(ePHI)的医疗工作负载,HIPAA 安全规则要求采取适当的保护措施。
流式传输可能使数据流图更加复杂,因为文本和音频可能同时经过多个服务。
这使得明确的架构文档变得更加重要。
选择流式 TTS 架构前需要基准测试的内容
不要用你笔记本电脑上的一个短句来测试 TTS 提供商,然后就认为评估完成了。
使用你实际的工作负载。
音频生成速度
并发性能
分块到达方差
长响应一致性
句子边界质量
适用时的电话质量
从部署区域的性能
还要测试失败路径。
TTS 连接在半句处关闭?
LLM 停止生成 token?
你的播放队列增长过大?
上游代理缓冲了本应是流式传输的响应?
网络从 Wi-Fi 切换到移动数据?
只有当每个组件都保持流式行为时,流式架构才是快速的。
一个缓冲的反向代理可能会悄无声息地将你的流式传输变回批响应。
流式还是批处理:实用决策框架
在以下情况下选择流式 TTS:
输出是动态生成的
用户正在交互式等待
首音频时间很重要
响应无法有效缓存
LLM 输出是增量式的
应用程序支持连接和缓冲区管理
在以下情况下选择批处理 TTS:
内容可以预生成
总渲染时间比首音频更重要
更简单的基础设施有价值
缓存能实质性减少合成量
当应用程序包含静态提示和动态响应的混合时,两者都可以使用。
这种混合设计很常见,而且通常比将所有语音强制通过相同路径更经济。
流式 TTS 并不自动优于批处理合成。
它解决的是一个特定问题:在完整合成作业完成之前,将有用的音频传递给听众。
对于构建交互式语音系统的开发者来说,主要经验教训是:
单独优化首音频时间,而不是总合成时间。
尽可能重叠 LLM 生成、语音合成和播放。
不要盲目地将单个 LLM token 发送给 TTS。
将句子和短语分割视为质量与延迟之间的权衡决策。
使用缓冲来吸收网络抖动,但保持缓冲区足够小以保持响应能力。
为背压、取消和用户中断做规划。
在服务器端保留经过身份验证的语音 API 调用。
特别是在流式模式下测试 SSML 和语音一致性。
当内容可预测时使用批处理合成和缓存。
对完整生产流水线进行基准测试,而不是孤立地测试模型。
一个语音应用程序感觉响应迅速还是感觉迟钝,其差异很少由单个延迟数字控制。
它来自于整个流水线如何重叠工作。
如果你想用你自己的提示和音频流水线来测试这个架构,请创建一个 API 密钥并开始使用 Smallest AI API 进行构建。