news 2026/9/24 14:47:01

PaddleSpeech 流式 TTS 在线引擎(Python 动态图后端)源码级解析与实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PaddleSpeech 流式 TTS 在线引擎(Python 动态图后端)源码级解析与实战指南
  • 人工智能
  • 语音
  • 音频

【免费下载链接】PaddleSpeech

Easy-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/gh_mirrors/pa/PaddleSpeech
点击查看免费下载

PaddleSpeech 的流式语音合成(Streaming TTS)服务在 docs/source/api/paddlespeech.server.engine.tts.online.python.rst 中对外公开了paddlespeech.server.engine.tts.online.python包,该包是服务端 TTS 引擎的Python 动态图推理后端(对应引擎类型tts_online)。本文以该 API 文档指向的模块为骨架,结合其底层实现 tts_engine.py、服务配置 tts_online_application.yaml 与官方示例 streaming_tts_server,完整讲解流式 TTS 引擎的初始化流程、分块(chunk)推理原理、pad/depad 机制、配置项含义以及 HTTP/WebSocket 服务接入方法。读完本文,你将能够从源码层面理解流式 TTS 的端到端调用链,并独立部署、配置和调用 PaddleSpeech 流式语音合成服务。

1. 模块定位:从 API 文档入口看在线 TTS 引擎

docs/source/api/paddlespeech.server.engine.tts.online.python.rst是一份 Sphinxautomodule风格的 API 文档骨架,它声明了三个关键信息:

  • 模块名:paddlespeech.server.engine.tts.online.python
  • 渲染方式::members::undoc-members::show-inheritance:,即自动提取模块内所有公开类、方法与继承关系;
  • 子模块:唯一的子模块paddlespeech.server.engine.tts.online.python.tts_engine

也就是说,该包的核心内容全部集中在 tts_engine.py 这一个文件中,它导出了__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']两个公开符号。从 online 包索引 可以看到,paddlespeech.server.engine.tts.online之下还存在一个onnx子包,二者分别对应配置中的引擎类型:

引擎类型推理后端模型名称后缀说明
tts_onlinePaddle 动态图(本包)fastspeech2_csmsc/fastspeech2_cnndecoder_csmscPython 动态图推理
tts_online-onnxONNX Runtimefastspeech2_csmsc_onnx/fastspeech2_cnndecoder_csmsc_onnx推理速度更快

本文聚焦于tts_online,即 Python 动态图后端。该引擎类层次上继承自 BaseEngine,BaseEngine使用Singleton元类保证全局只有一个引擎实例,并定义了init()run()postprocess()三个生命周期方法。

2. 引擎内部三大组件与整体调用链

从源码结构看,tts_engine.py内部由三个类协同工作:

  1. TTSServerExecutor(继承自paddlespeech.cli.tts.infer.TTSExecutor):负责模型文件的解析、下载与加载,将 AM(声学模型)、Vocoder(声码器)、前端(frontend)初始化为可推理状态;
  2. TTSEngine(继承自BaseEngine):服务级引擎,负责读取 yaml 配置、校验模型组合与流式参数、设置推理设备,并持有唯一的TTSServerExecutor
  3. PaddleTTSConnectionHandler:连接处理器,负责对每条合成请求执行流式分块推理、去 pad(depadding)、float32 转 PCM、base64 编码,并以生成器(generator)的方式逐块产出音频。

一次流式合成的调用链可以概括为:

WebSocket/HTTP 请求 │ ▼ paddlespeech/server/ws/tts_api.py (按 engine_type 选择 handler) │ ▼ PaddleTTSConnectionHandler.run(sentence, spk_id) │ ▼ PaddleTTSConnectionHandler.infer(...) -- 前端文本转音素 -> AM 推理 -> Mel 分块 -> Vocoder 推理 │ ▼ float2pcm -> base64 编码,逐块 yield

3. 引擎初始化:模型解析、下载与加载(TTSServerExecutor)

TTSServerExecutor.__init__中创建了CommonTaskResource(task='tts', model_format='dynamic', inference_mode='online'),即按动态图格式在线推理模式来定位 TTS 模型资源。

3.1_init_from_path:AM 与 Vocoder 的资源解析

_init_from_path是模型初始化的核心入口,签名如下:

def _init_from_path( self, am: str = 'fastspeech2_csmsc', am_config=None, am_ckpt=None, am_stat=None, phones_dict=None, tones_dict=None, speaker_dict=None, voc: str = 'mb_melgan_csmsc', voc_config=None, voc_ckpt=None, voc_stat=None, lang: str = 'zh'):

其关键逻辑包括:

  • 预训练模型自动下载:当am_ckptam_configam_statphones_dict任一为空时,use_pretrained_am = True,引擎会以am + '-' + lang(如fastspeech2_csmsc-zh)作为model_tag调用set_task_model(model_type=0)自动下载官方预训练模型,并从资源目录解析出configckptspeech_statsphones_dict等文件的真实路径;Vocoder 同理(model_type=1)。如果用户显式指定了所有路径,则skip_download=True,直接使用绝对路径加载本地模型。
  • 词汇表构建:读取phones_dict(音素字典)得到vocab_size,用于构造 AM 模型输入维度。
  • 前端选择lang == 'zh'时使用 zh_frontend.Frontend(支持tone_vocab_path声调字典);lang == 'en'时使用 en_frontend.English。
  • AM 名称归一化self.am_name = am[:am.rindex('_')],即fastspeech2_csmsc归一为fastspeech2fastspeech2_cnndecoder_csmsc归一为fastspeech2_cnndecoder;随后通过get_model_class动态获取模型类。

3.2get_model_info:加载模型与归一化统计量

get_model_info(field, model_name, ckpt, stat)field区分加载逻辑:

  • field == "am":以idim=self.vocab_sizeodim=self.am_config.n_mels构造声学模型,加载paddle.load(ckpt)["main_params"]
  • field == "voc":以**self.voc_config["generator_params"]构造声码器,加载paddle.load(ckpt)["generator_params"],并调用model.remove_weight_norm()移除权重归一化(推理加速);
  • 二者都会读取stat(mean/std 统计量文件)并转为paddle.Tensor

加载完成后,AM 会包一层ZScore归一化器并套上<am_name>_inference推理封装类(如fastspeech2_inference),Vocoder 同样以ZScore+<voc_name>_inference封装,二者均置为eval()模式。

3.3 采样率一致性校验

TTSEngine.init()中有一个容易被忽略但重要的断言:

assert self.executor.am_config.fs == self.executor.voc_config.fs, \ "The sample rate of AM and Vocoder model are different, please check model." self.sample_rate = self.executor.am_config.fs

流式 TTS 要求 AM 与 Vocoder 的采样率一致(默认均为 24000 Hz),合成音频的采样率最终取自 AM 配置。同时在初始化完成后,voc_upsample = self.executor.voc_config.n_shift(默认 300),即声码器的 hop 长度,它决定 Mel 帧数到音频采样点数的放大倍数。

4. TTSEngine.init:配置校验与流式分块参数

TTSEngine.init(config)是服务启动时的入口,除了模型初始化外,还做了以下硬性校验(对应 tts_online_application.yaml 中tts_online一节):

  • AM 模型只允许fastspeech2_csmscfastspeech2_cnndecoder_csmsc(后者支持流式 AM 推理);
  • Vocoder只允许hifigan_csmscmb_melgan_csmsc(二者均支持流式推理);
  • voc_block > 0voc_pad > 0
  • device参数:配置中可写cpugpu:id,未配置时回退到paddle.get_device(),随后paddle.set_device(device)生效;设备设置失败时记录 error 并返回False

初始化成功后,引擎从配置中取出四个流式关键参数:

self.am_block = self.config.am_block self.am_pad = self.config.am_pad self.voc_block = self.config.voc_block self.voc_pad = self.config.voc_pad self.am_upsample = 1 self.voc_upsample = self.executor.voc_config.n_shift
参数含义默认值说明
am_blockAM 推理 chunk 的有效帧数72仅对fastspeech2_cnndecoder生效
am_padchunk 前后各叠加的帧数,用于消除流式误差12设为 12 时流式与非流式合成结果一致
voc_blockVocoder 推理 chunk 的有效帧数36
voc_padchunk 前后各叠加的帧数14见下文按模型区分的最小值
am_upsampleAM 帧放大倍数1
voc_upsampleMel 帧到采样点的放大倍数300取自 voc 配置n_shift

5. 流式推理核心:PaddleTTSConnectionHandler

PaddleTTSConnectionHandler是流式合成的"心脏"。它的infer()方法使用@paddle.no_grad()装饰,以生成器方式逐块产出sub_wav(numpy 数组)。

5.1 前端处理与计时

zh文本,调用executor.frontend.get_input_ids(text, merge_sentences=False, get_tone_ids=False)得到phone_ids(音素 id 序列);对en文本走English前端。随后记录frontend_time,并针对每一条音素序列执行 AM + Vocoder 推理。

5.2 模式一:fastspeech2_csmsc(AM 一次性 + Vocoder 流式)

mel = self.executor.am_inference(part_phone_ids) # AM 一次性产出全部 Mel mel_chunks = get_chunks(mel, self.voc_block, self.voc_pad, "voc") for i, mel_chunk in enumerate(mel_chunks): sub_wav = self.executor.voc_inference(mel_chunk) # 声码器逐块推理 sub_wav = self.depadding(sub_wav, voc_chunk_num, i, self.voc_block, self.voc_pad, self.voc_upsample) yield sub_wav

这种模式下 AM 不流式,只有 Vocoder 按voc_block分块,实现"首包低延迟"的流式听感。

5.3 模式二:fastspeech2_cnndecoder_csmsc(AM + Vocoder 双流式)

该模式真正实现了 AM 与 Vocoder 的双重流式:

  1. 先用am_inference.encoder_infer(part_phone_ids)一次性得到 encoder 隐层orig_hs
  2. 计算 Mel 总长mel_len与 vocoder chunk 数量voc_chunk_num = ceil(mel_len / voc_block)
  3. get_chunks(orig_hs, self.am_block, self.am_pad, "am")将隐层切块,逐块调用decoder(hs)postnet(...)得到归一化 Mel;
  4. 通过denorm(normalized_mel, am_mu, am_std)(见 util.py 中的denorm(data, mean, std) = data * std + mean)反归一化;
  5. depadding去除每块的前后 pad,并np.concatenate累积到mel_streaming
  6. 当累积的 Mel 帧数足够(mel_streaming.shape[0] >= end)时,按滑动窗口start:end交给 vocoder 推理并 yield 音频块,随后更新startend滑窗位置。

这里start = max(0, voc_chunk_id * voc_block - voc_pad)end = min((voc_chunk_id+1) * voc_block + voc_pad, mel_len),即相邻 vocoder chunk 之间有voc_pad帧的重叠,重叠部分在depadding时被裁剪,从而避免流式推理在块边界产生音质跳变。

5.4 depadding:流式去重叠原理

depadding(data, chunk_num, chunk_id, block, pad, upsample)的实现按 chunk 位置分三种情况:

  • 首块chunk_id == 0):只保留前block * upsample个采样点(去掉尾部 pad);
  • 末块chunk_id == chunk_num - 1):去掉头部front_pad * upsample个采样点;
  • 中间块:取[front_pad * upsample : (front_pad + block) * upsample],同时去掉头、尾 pad。

其中front_pad = min(chunk_id * block, pad)保证首块之后的重叠量不超过pad。乘以upsample是因为 pad 的单位是 Mel 帧,需要放大为采样点数(vocoder 阶段upsample = voc_upsample,AM 阶段am_upsample = 1)。

与之配套的切块工具是 util.py 中的get_chunks(data, block_size, pad_size, step):它以ceil(data_len / block_size)决定 chunk 数量,每块取[i*block - pad, (i+1)*block + pad]的闭区间(含边界),step参数决定按哪个维度切分("am"data.shape[1]"voc"data.shape[0])。

5.5 时序指标与 RTF

infer()内部埋点统计了三个关键时序:

  • first_am_infer:首次 AM 推理耗时(从前端结束起算);
  • first_voc_infer:首次 Vocoder 推理耗时(从首次 AM 结束起算);
  • first_response_time:首包响应时间(从前端开始到首段音频产出),这是流式 TTS 最核心的体验指标。

run()方法完成推理后的后处理与统计:

wav = float2pcm(wav) # float32 -> int16 wav_bytes = wav.tobytes() # -> bytes wav_base64 = base64.b64encode(wav_bytes).decode('utf8') yield wav_base64

其中float2pcm实现在 audio_process.py,将范围 [-1, 1] 的浮点信号缩放到 int16 整数域并裁剪。全部 chunk 产完后,run()计算音频总时长duration = len(wav_all) / sample_rate,并输出日志:

sentence: ... The durations of audio is: X s first response time: X s final response time: X s RTF: final_response_time / duration Other info: front time, first am infer time, first voc infer time

RTF(Real-Time Factor)即合成耗时与音频时长之比,是评估流式合成性能的关键指标。仓库还提供了 util.py 中的count_engine(logfile)工具,可直接解析nohup.out日志批量统计平均首包响应、平均尾包响应、平均时长与整体 RTF。

6. 服务配置文件详解:tts_online_application.yaml

流式 TTS 服务使用 paddlespeech/server/conf/tts_online_application.yaml 作为默认配置,demo 目录 demos/streaming_tts_server/conf/tts_online_application.yaml 中也有同款可运行版本。配置分三大部分:

6.1 SERVER SETTING(服务设置)

host: 0.0.0.0 port: 8092 protocol: 'http' # 可选 ['websocket', 'http'] engine_list: ['tts_online-onnx'] # 可选 ['tts_online', 'tts_online-onnx']
  • protocol:服务使用的网络协议,目前支持httpwebsocket
  • engine_list:服务包含的引擎列表,格式为<语音任务>_<引擎类型>;流式 TTS 使用tts_online(Python 动态图)或tts_online-onnx(ONNX Runtime,速度更快);
  • 注意:若在容器内可正常启动服务但客户端访问 IP 不可达,可将host改为本地实际 IP。

6.2 tts_online 引擎配置(本包对应部分)

tts_online: am: 'fastspeech2_csmsc' # 可选 fastspeech2_csmsc / fastspeech2_cnndecoder_csmsc am_config: am_ckpt: am_stat: phones_dict: tones_dict: speaker_dict: spk_id: 0 voc: 'mb_melgan_csmsc' # 可选 mb_melgan_csmsc / hifigan_csmsc voc_config: voc_ckpt: voc_stat: lang: 'zh' device: 'cpu' # 可选 'gpu:id' 或 'cpu' am_block: 72 am_pad: 12 voc_block: 36 voc_pad: 14

所有模型路径字段(am_configam_ckpt等)留空时引擎会自动下载官方预训练模型。am_block/am_pad仅对fastspeech2_cnndecoder_csmsc生效;voc_pad的推荐取值与模型相关,详见下一节。

6.3 pad 参数选取的工程经验

根据 demo 文档 与配置文件注释,pad 的取值直接影响流式合成音质:

  • am_pad = 12时,流式 AM 合成音频与非流式完全一致;
  • mb_melgan_csmscvoc_pad = 14时流式与非流式一致;最小可设为 7(听感正常),小于 7 听感异常;
  • hifigan_csmscvoc_pad = 19时流式与非流式一致;设为 14 时听感正常;
  • 推理速度:mb_melgan > hifigan;音频质量:mb_melgan < hifigan

仓库中 tts_online_application.yaml 的tts_online-onnx一节还展示了 ONNX 后端的扩展字段:am_ckpt为模型列表(cnndecoder 时按 [encoder, decoder, postnet] 顺序)、am_sess_conf/voc_sess_conf(含use_trtcpu_threads)以及voc_upsample(须与 voc 配置的n_shift一致)。

7. 服务部署与客户端调用

7.1 服务端启动

命令行方式(推荐):

paddlespeech_server start --config_file ./conf/tts_online_application.yaml
  • config_file:服务配置文件,默认./conf/tts_online_application.yaml
  • log_file:日志文件,默认./log/paddlespeech.log

启动成功后日志会先打印 3 次 warm up 的首包响应时间,随后出现Uvicorn running on http://0.0.0.0:8092,表明 HTTP 服务已在 8092 端口就绪。若将protocol改为websocket,则启动同样的命令即可提供 WebSocket 流式接口。

Python API 方式:

from paddlespeech.server.bin.paddlespeech_server import ServerExecutor server_executor = ServerExecutor() server_executor( config_file="./conf/tts_online_application.yaml", log_file="./log/paddlespeech.log")

7.2 HTTP 协议客户端

命令行(若127.0.0.1不可达,替换为实际服务 IP):

paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol http --input "您好,欢迎使用百度飞桨语音合成服务。" --output output.wav

客户端参数一览:

参数含义默认值
server_ip服务端 IP127.0.0.1
port服务端口8092
protocol服务协议,可选 http / websockethttp
input待合成文本(必填)
spk_id说话人 id(多说话人场景)0
output输出音频路径,None 表示不保存None
play是否边合成边播放(依赖 pyaudio)False

Python API 方式:

from paddlespeech.server.bin.paddlespeech_client import TTSOnlineClientExecutor executor = TTSOnlineClientExecutor() executor( input="您好,欢迎使用百度飞桨语音合成服务。", server_ip="127.0.0.1", port=8092, protocol="http", spk_id=0, output="./output.wav", play=False)

客户端成功输出示例:

tts http client start 句子:您好,欢迎使用百度飞桨语音合成服务。 首包响应:0.18863153457641602 s 尾包响应:3.1427218914031982 s 音频时长:3.825 s RTF: 0.8216266382753459 音频保存至:output.wav

7.3 WebSocket 协议客户端

将配置中protocol改为websocket后重启服务,客户端命令只需更换协议参数:

paddlespeech_client tts_online --server_ip 127.0.0.1 --port 8092 --protocol websocket --input "您好,欢迎使用百度飞桨语音合成服务。" --output output.wav

7.4 WebSocket 服务端协议流程

WebSocket 端点在 tts_api.py 的/paddlespeech/tts/streaming路由中实现,协议分三类消息:

  1. start 信号:客户端发送{"signal": "start"},服务端创建PaddleTTSConnectionHandler(按tts_engine.engine_type动态导入 python 或 onnx 版本),返回{"status": 0, "signal": "server ready", "session": <uuid>}
  2. 合成请求:客户端发送{"text": "...", "spk_id": 0},服务端调用connection_handler.run(...)并逐块返回{"status": 1, "audio": <base64>};合成完毕返回{"status": 2, "audio": ''},出错返回{"status": -1, "audio": ''}
  3. end 信号:客户端发送{"signal": "end"},服务端关闭连接并返回{"status": 0, "signal": "connection will be closed"}

这就是流式 TTS 能够"边合成边推送"的协议基础:每一段音频(约一个voc_block对应的时长)独立编码为 base64 后通过 WebSocket 帧即时下发。

8. 使用限制与注意事项

  • 说话人:当前代码只支持单说话人模型,spk_id的选择并不生效;
  • 不支持的能力:流式 TTS 不支持更换采样率、变速、变音量等功能;
  • 模型组合:流式引擎仅支持fastspeech2/fastspeech2_cnndecoder(AM)与hifigan/mb_melgan(Vocoder)的组合,且 AM 与 Vocoder 采样率必须一致;
  • 依赖版本:官方 demo 推荐使用 paddlepaddle 2.4rc 及以上版本;若使用简单模式安装,需要自行参考 conf 目录 下的 yaml 文件准备配置;
  • 设备占用:若设置device失败,请检查该设备是否已被占用以及 yaml 中device参数格式(cpugpu:id)。

9. 进一步阅读

  • 流式 TTS 在线引擎实现:paddlespeech/server/engine/tts/online/python/tts_engine.py
  • ONNX 版在线引擎(对比参考):paddlespeech/server/engine/tts/online/onnx/tts_engine.py
  • 引擎基类:paddlespeech/server/engine/base_engine.py
  • 服务配置:paddlespeech/server/conf/tts_online_application.yaml
  • 分块与统计工具:paddlespeech/server/utils/util.py
  • WebSocket 端点:paddlespeech/server/ws/tts_api.py
  • 完整部署示例:demos/streaming_tts_server/README_cn.md
  • 人工智能
  • 语音
  • 音频

【免费下载链接】PaddleSpeech

Easy-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/gh_mirrors/pa/PaddleSpeech
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 14:46:01

抛载检测 → 重复控制 RPT 清窗逻辑 → RPT 缓投使能 → 二阶滤波处理

可以专门 提供 储能一体机ARM通信管理单元,从ARM单元代码,主DSP代码、方案、硬件软件全部开源;一体化解决方案 提供西门子200全套解决方案,软硬件解决方案,全部源代码。 抛载检测 → 重复控制 RPT 清窗逻辑 → RPT 缓投使能 → 二阶滤波处理 前置背景: 你的逆变器是50H…

作者头像 李华