恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
PaddleSpeech 流式 TTS 推理与实时播放:stream_play_tts 模块原理与实践
首页
资讯中心
/
PaddleSpeech 流式 TTS 推理与实时播放:stream_play_tts 模块原理与实践
PaddleSpeech 流式 TTS 推理与实时播放:stream_play_tts 模块原理与实践
发布时间:2026/9/24 14:43:36
人工智能语音音频NLP媒体生成【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址https://gitcode.com/paddlepaddle/PaddleSpeech点击查看免费下载本篇文章以 paddlespeech.t2s.exps.stream_play_tts 模块为主体讲解 PaddleSpeech 中基于 ONNX Runtime 的流式语音合成Streaming TTS实现如何在 CPU 上使用 fastspeech2_cnndecoder 流式声学模型与 mb_melgan 流式声码器实现边合成边播放的实时体验。读完本文你将掌握流式 AM/Vocoder 的分块chunk推理、去 paddingdepadding拼接、滑动窗口机制以及如何用 pyaudio 实时播放并导出流式合成结果。模块定位把流式 TTS 跑成本地脚本paddlespeech.t2s.exps.stream_play_tts是 PaddleSpeech 中一个独立的实验experiment级脚本模块与基于服务端架构的 demos/streaming_tts_server 不同它以单机脚本形式演示了流式 TTS 的完整链路中文文本前端 → 流式 AM声学模型分块推理 → 流式 Vocoder声码器分块推理 → 实时声卡播放 → 保存 wav。模块的核心结论是不需要等整句话合成完毕只要第一个 AM chunk 的 Mel 帧数达到 Vocoder 的 chunk 大小就可以立刻开始播放第一批音频从而把首包延迟压到极低。该模块对应的 API 文档为 docs/source/api/paddlespeech.t2s.exps.stream_play_tts.rst其内容通过automodule指令直接引用本模块源码中的 docstring 与成员。运行前的准备模型文件与依赖下载并解压模型源码注释stream_play_tts.py要求首次运行前在执行目录下下载并解压两个 ONNX 模型包fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0.zip流式 AM声学模型解压后包含phone_id_map.txt、speech_stats.npy、fastspeech2_csmsc_am_encoder_infer.onnx、fastspeech2_csmsc_am_decoder.onnx、fastspeech2_csmsc_am_postnet.onnx等文件mb_melgan_csmsc_onnx_0.2.0.zip流式声码器解压后包含mb_melgan_csmsc.onnx。下载地址wget 命令见 stream_play_tts.py 文件头部注释下载后使用unzip解压到当前目录即可。注意脚本中的路径均为相对路径因此必须在解压目录下运行脚本。Python 依赖脚本 import 了以下关键库运行前需确保已安装依赖用途onnxruntimeONNX 模型推理引擎脚本以CPUExecutionProvider在 CPU 上运行pyaudio实时声卡播放numpy张量运算与拼接soundfile最终结果导出为 wavpaddle经由 Frontend 间接使用文本前端将文本转为 phone id同时脚本复用了 PaddleSpeech server 模块的工具函数paddlespeech.server.utils.util.denorm流式 AM 输出的反归一化paddlespeech.server.utils.util.get_chunks按 block/pad 切分 chunkpaddlespeech.server.utils.audio_process.float2pcmfloat32 转 int16 PCMpaddlespeech.t2s.frontend.zh_frontend.Frontend中文文本前端。核心参数block 与 pad 的物理含义脚本顶部定义了一组流式推理的全局常量stream_play_tts.pyvoc_block 36 # 声码器每个 chunk 的有效 Mel 帧数 voc_pad 14 # 声码器每个 chunk 前后各补的 Mel 帧数 am_block 72 # 声学模型每个 chunk 的有效帧数 am_pad 12 # 声学模型每个 chunk 前后各补的帧数 voc_upsample 300 # 声码器上采样倍数对应 voc 配置的 n_shift流式推理的基本矛盾是模型在推理单个 chunk 时chunk 边界处的帧会因为缺少上下文而产生误差。解决办法是每个 chunk 除了有效帧block还要在前后各多取pad帧参与推理推理完成后只保留中间有效部分两侧 padding 结果被丢弃。depadding()函数就是干这件事的首块chunk_id 0只取前block * upsample个采样点尾块chunk_id chunk_num - 1丢弃开头front_pad * upsample个采样点中间块取[front_pad * upsample, (front_pad block) * upsample)区间。这里的front_pad min(chunk_id * block, pad)保证第一块不会取负索引。详细实现见 stream_play_tts.py。这些参数的取值并非随意它们与合成质量直接相关在流式 TTS 服务配置 demos/streaming_tts_server/conf/tts_online_application.yaml 中有更完整的说明am_block: 72, am_pad: 12am_pad12时流式 AM 合成音频与非流式完全一致仅对 fastspeech2_cnndecoder 生效voc_block: 36, voc_pad: 14mb_melgan 在voc_pad14时流式与非流式一致最低可设到 7听感正常低于 7 会出现异常听感voc_upsample: 300必须与 vocoder 配置中的n_shift一致tts_online_application.yaml它决定了1 帧 Mel 对应多少采样点是 Mel 帧与波形采样点换算的关键。模型加载与文本前端加载 ONNX Session脚本为 AM 的三个子模型和 vocoder 分别创建onnxruntime.InferenceSessionstream_play_tts.py全部使用CPUExecutionProvideram_encoder_infer将 phone id 序列编码为 hidden stateam_decoder将 hidden state chunk 解码为 Melam_postnet对 Mel 做后处理增强残差修正最终输出为 decoder 输出 postnet 输出voc_melgan将 Mel chunk 上采样为波形。之所以把 AM 拆成 encoder/decoder/postnet 三个 ONNX正是因为只有 decoder 和 postnet 是逐 chunk 流式执行的encoder 仍可一次性处理整句 phone id——这是 fastspeech2_cnndecoder 支持流式 AM 的结构基础。文本前端使用 Frontendpaddlespeech.t2s.frontend.zh_frontend将中文文本转为 phone idphones_dict fastspeech2_cnndecoder_csmsc_streaming_onnx_1.0.0/phone_id_map.txt frontend Frontend(phone_vocab_pathphones_dict, tone_vocab_pathNone)在inference_stream()中调用frontend.get_input_ids(text, merge_sentencesFalse, get_tone_idsFalse)获得phone_idsstream_play_tts.py。get_input_ids会先经过get_phonemes做中文分词、注音与韵律处理再把音素映射为词典 idmerge_sentencesFalse表示按句切分、逐句返回脚本外层用for i in range(len(phone_ids))遍历每一句get_input_ids。由于输入是 numpy 数组该路径可以无缝喂给 onnxruntime session。流式 AM 推理chunk 级 Mel 生成流式 AM 的流程inference_stream如下整句编码将一句 phone id 送入am_encoder_infer_sess得到整句的 hidden stateorig_hs其 shape 为[1, mel_len, dim]切 chunk调用get_chunks(orig_hs, am_block, am_pad, am)切出am_chunk_num个 chunk。get_chunksutil.py中stepam时沿第 1 维时间帧维度切分每块为[1, block2*pad, dim]逐 chunk 推理每个 chunkhs依次送入am_decoder_sess得到 Mel再转置为[B, C, T]送入am_postnet_sess最终 Mel 为decoder 输出 postnet 输出残差结构stream_play_tts.py反归一化因为流式 AM 模型训练时对 Mel 做了均值方差归一化推理后需用speech_stats.npy中的am_mu、am_std做data * std mean还原denorm由np.load(am_stat_path)加载统计量去 padding对反归一化后的 chunk 调用depadding(..., upsample1)丢弃两侧 pad 帧Mel 维度上 upsample 为 1并np.concatenate拼接成mel_streaming。经过以上步骤mel_streaming就是到目前为止已经高质量合成出的 Mel 帧序列它会被喂给下一阶段的流式 vocoder。流式 Vocoder 推理滑动窗口与实时播放流式 vocoder 的核心是双指针滑动窗口stream_play_tts.pymel_len orig_hs.shape[1] voc_chunk_num math.ceil(mel_len / voc_block) start 0 end min(voc_block voc_pad, mel_len)当流式 AM 累积的mel_streaming.shape[0] end时Mel 帧足够一次 vocoder 推理立即取mel_streaming[start:end, :]送入voc_melgan_sess得到波形 chunk经depadding(..., upsamplevoc_upsample)去掉 padding 采样点后用yield抛出。随后窗口滑动voc_chunk_id 1 start max(0, voc_chunk_id * voc_block - voc_pad) end min((voc_chunk_id 1) * voc_block voc_pad, mel_len)start回退voc_pad帧保证 chunk 间上下文衔接end用min限制在mel_len内。因为inference_stream是生成器函数每yield一个波形 chunk主循环就可以立刻播放一段音频实现真正的流式播放这正是首包延迟低的原因。主流程Warmup、实时播放与导出__main__中的运行逻辑stream_play_tts.py分为三步Warmuponnxruntime 首次推理开销较大session 初始化、算子预热先用哈哈哈哈空转一遍全部 session避免把首次推理耗时算进首包延迟stream_play_tts.py。这与流式 TTS 服务启动时打印的 warm up 日志见 demos/streaming_tts_server/README.md是同一设计思路pyaudio 实时播放以int16、单声道、24000 Hz打开输出流与 AM/Vocoder 的采样率一致。对每个sub_wavchunk先用 float2pcm 把 [-1, 1] 的 float32 转为 int16 PCMsig * abs_max offset缩放并 clip再tobytes()后stream.write()写入声卡实现边合成边播放。每收到一个 chunk 打印一次响应耗时导出 wav把各 chunkflatten()后np.concatenate拼成完整波形用soundfile以 24000 Hz 写入demo_stream.wavstream_play_tts.py。运行方式python paddlespeech/t2s/exps/stream_play_tts.py运行时会在控制台逐 chunk 打印响应时间最终在脚本目录下生成demo_stream.wav同时扬声器实时播放合成语音。与流式 TTS 服务的参数对应关系本脚本采用的参数72/12/36/14/300正是流式 TTS 服务中tts_online-onnx引擎的默认配置tts_online_application.yaml。二者共享同一套流式推理约束支持流式 AM 的模型只有fastspeech2_cnndecoder系列非流式fastspeech2不支持 AM 分块am_block/am_pad无效支持流式 vocoder 的有mb_melgan与hifigan其中 hifigan 需要更大的 padvoc_pad19时与非流式一致14时听感正常voc_upsample必须与 vocoder 配置的n_shift一致否则波形时长会错误推理速度 mb_melgan hifigan音频质量反之demos/streaming_tts_server/README.md。因此理解本脚本就等于理解了 PaddleSpeech 流式 TTS 服务的核心推理内核服务端只是在生成器之上封装了 HTTP/WebSocket 传输协议与客户端播放而stream_play_tts.py用最少的代码把这条流式链路完整、可运行地呈现在读者面前。总结paddlespeech.t2s.exps.stream_play_tts是学习 PaddleSpeech 流式 TTS 原理的最佳入口。它以约 180 行代码串联起文本前端、流式 AMencoder/decoder/postnet 三子模型 get_chunks/denorm/depadding、流式 vocoder双指针滑动窗口与实时播放pyaudio四大环节。核心可复用的经验包括用pad帧消除分块边界误差、用生成器 yield实现逐 chunk 输出、用 warmup 规避 onnxruntime 首次推理开销。若需在生产环境使用同等能力可参考 demos/streaming_tts_server 部署为服务化形态。赞分享人工智能语音音频NLP媒体生成【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址https://gitcode.com/paddlepaddle/PaddleSpeech点击查看免费下载相关推荐PaddleSpeech 流式 TTS 实战基于 ONNX Runtime 的 stream_play_tts 模块源码解析与边合成边播放实现PaddleSpeech 流式 TTS 实战基于 ONNX Runtime 的 stream_play_tts 模块源码解析与边合成边播放实现 本篇文章以 P人工智能语音音频PaddleSpeech 流式 TTS 服务引擎深度解析tts_engine 模块的在线语音合成原理与实践PaddleSpeech 流式 TTS 服务引擎深度解析 tts_engine 模块的在线语音合成原理与实践 导读 本文围绕 PaddleSpeech 服务端人工智能语音音频PaddleSpeech流式TTS技术解析实时语音合成的实现原理PaddleSpeech流式TTS技术解析实时语音合成的实现原理 引言实时语音合成的技术挑战 在智能客服、语音助手等实时交互场景中用户对语音合成的响应速度人工智能语音音频上一篇alpaca.cpp性能基准行业标准测试集跑分结果下一篇RegExr产品路线图制定用户需求与技术可行性平衡创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考