- 人工智能
- 语音
- 音频
【免费下载链接】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.
本文围绕 PaddleSpeech 仓库中
paddlespeech.server.engine.tts.paddleinference包展开,系统讲解该包中TTSEngine、TTSServerExecutor、PaddleTTSConnectionHandler三个核心类的职责与调用链,并结合 application.yaml 中的tts_inference配置段、paddle_predictor.py 的 Predictor 封装以及 tts_api.py 的 REST 接口,给出从配置文件到 HTTP 请求的完整离线 TTS 服务搭建与二次开发方案。读者读完可掌握基于 Paddle Inference 静态模型的高性能 TTS 服务引擎的内部结构与部署方法。
一、模块定位:离线 TTS 服务引擎的 Inference 分支
PaddleSpeech 的服务端(paddlespeech/server)为语音合成(TTS)提供了多套引擎实现,按引擎类型划分位于 engine/tts 目录下:
| 引擎目录 | 引擎类型 | 模型格式 | 适用场景 |
|---|---|---|---|
tts/paddleinference | inference | Paddle Inference 静态图模型(.pdmodel/.pdiparams) | 离线批量合成、追求低推理开销的线上服务 |
tts/python | python | 动态图模型(config/ckpt/stat) | 开发调试、动态图推理 |
tts/online(含onnx子目录) | online/online-onnx | 流式模型 | 流式(流式)语音合成 |
本文的主角paddlespeech.server.engine.tts.paddleinference即对应上表中的inference 类型。其 API 文档入口为 paddlespeech.server.engine.tts.paddleinference.rst,该文档通过automodule指令将包的__init__暴露内容与子模块 paddlespeech.server.engine.tts.paddleinference.tts_engine.rst 中的类成员自动生成 API 索引。包结构非常简单,仅包含两个文件:
__init__.py:包初始化(仅含 Apache License 头,无业务逻辑);tts_engine.py:全部引擎实现,约 523 行,声明了__all__ = ['TTSEngine', 'PaddleTTSConnectionHandler']。
从源码结构可以看出,该包的设计目标十分明确:复用TTSExecutor的前端(Frontend)能力,将声学模型(AM)与声码器(Vocoder)替换为 Paddle Inference 静态图 Predictor,以服务于离线 TTS 服务场景。
二、类结构与核心职责
在 tts_engine.py 中,三个类构成一条清晰的"执行器 → 引擎 → 连接处理器"分层链路:
TTSServerExecutor(模型资源加载 + 推理) ↑ 继承 TTSExecutor(paddlespeech.cli.tts.infer,动态图推理基类) TTSEngine(服务引擎生命周期管理,单例) └─ 持有 TTSServerExecutor PaddleTTSConnectionHandler(连接处理器,封装请求级 run/postprocess) └─ 继承 TTSServerExecutor,复用其推理能力2.1 TTSServerExecutor:静态模型资源管理与推理
TTSServerExecutor继承自paddlespeech.cli.tts.infer.TTSExecutor,在__init__中通过CommonTaskResource(task='tts', model_format='static')声明以静态模型格式管理任务资源。其_init_from_path方法承担全部初始化工作,关键参数与默认值如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
am | fastspeech2_csmsc | 声学模型名,可选fastspeech2_csmsc、speedyspeech_csmsc等 |
am_model/am_params | None | AM 静态模型.pdmodel/.pdiparams路径,缺省时自动下载预训练模型 |
am_sample_rate | 24000 | AM 输出采样率 |
phones_dict/tones_dict/speaker_dict | None | 音素表 / 声调表 / 说话人表路径 |
voc | pwgan_csmsc | 声码器名,可选pwgan_csmsc、mb_melgan_csmsc、hifigan_csmsc |
voc_model/voc_params | None | 声码器静态模型路径 |
voc_sample_rate | 24000 | 声码器输出采样率 |
lang | zh | 语言,支持zh/en |
am_predictor_conf/voc_predictor_conf | None | Predictor 配置字典 |
初始化流程可归纳为四步(对应源码 tts_engine.py):
- AM 资源解析:若未显式指定
am_model、am_params、phones_dict,则use_pretrained_am=True,通过task_resource.set_task_model(model_tag=am + '-' + lang, model_type=0, ...)自动下载对应静态模型;否则读取本地绝对路径。 - Vocoder 资源解析:逻辑与 AM 相同,
model_type=1表示声码器任务。 - 字典加载:读取
phones_dict得到词表大小vocab_size;若模型为speedyspeech则加载tones_dict得到tone_size;若为多说话人模型(如aishell3、vctk)则加载speaker_dict得到spk_num。 - 前端与 Predictor 构建:
lang='zh'时使用paddlespeech.t2s.frontend.zh_frontend.Frontend,lang='en'时使用paddlespeech.t2s.frontend.en_frontend.English;随后分别调用init_predictor创建 AM 与 Vocoder 两个 Predictor。
2.2 infer:文本到语音的推理主流程
infer方法(tts_engine.py)标注了@paddle.no_grad(),其执行链路为:
- 模型名解析:
am_name = am[:am.rindex('_')]提取声学模型名(如fastspeech2、speedyspeech),am_dataset = am[am.rindex('_') + 1:]提取数据集标识(如csmsc、aishell3、vctk)。 - 前端文本转 ID:对中文文本调用
frontend.get_input_ids(text, merge_sentences=False, get_tone_ids=...);当模型为speedyspeech时get_tone_ids=True,额外返回tone_ids。 - 分句推理:对每一句 phone ID:
speedyspeech:将phone_ids与tone_ids两个输入送入 AM Predictor;fastspeech2多说话人版本(am_dataset为aishell3/vctk):输入[phone_ids, np.array([spk_id])];单说话人版本仅输入phone_ids;- 将 AM 输出的 mel 谱送入 Vocoder Predictor 得到波形,逐句
paddle.concat拼接。
- 耗时统计:分别记录
self.frontend_time、self.am_time、self.voc_time,供上层 RTF 计算使用。
值得注意的实现细节是:源码注释明确指出"multi speaker do not have static model",即多说话人 fastspeech2 在静态推理时通过spk_id参数在请求级指定说话人,但spk_id仅作为 AM 输入参与推理。
2.3 TTSEngine:服务引擎生命周期
TTSEngine继承BaseEngine,是一个单例服务引擎,init(config)方法完成:
- 创建
TTSServerExecutor并保存config,设置engine_type = "inference"; - 设备选择优先级:
am_predictor_conf.device→voc_predictor_conf.device→paddle.get_device(),随后调用paddle.set_device; - 将配置逐项透传给
executor._init_from_path,任一环节异常则返回False并输出错误日志,成功时打印Initialize TTS server engine successfully on device: ...。
这里体现出engine_type: "inference"的字符串值正是后续 REST 路由选择本模块PaddleTTSConnectionHandler的判断依据(见 tts_api.py)。
2.4 PaddleTTSConnectionHandler:请求级处理
PaddleTTSConnectionHandler继承TTSServerExecutor,构造时从tts_engine中取出已初始化的executor、frontend、am_predictor、voc_predictor与config,从而避免重复加载模型。其核心方法:
postprocess(wav, original_fs, target_fs=0, volume=1.0, speed=1.0, audio_path=None)(tts_engine.py)按顺序执行:
- 采样率转换:
target_fs == 0或大于模型采样率时保持原样,否则用librosa.resample重采样; - 音量调节:
wav_vol = wav_tar_fs * volume; - 语速调节:调用
paddlespeech.server.utils.audio_process.change_speed(依赖 soxbindings,Windows 不支持时会抛出ServerBaseException); - 编码与保存:用
soundfile将音频写入内存缓冲区并转 base64 字符串;若指定audio_path,支持.wav(sf.write)与.pcm(int16 归一化后二进制写入)两种格式。
run(sentence, spk_id=0, speed=1.0, volume=1.0, sample_rate=0, save_path=None)(tts_engine.py)是完整的请求处理入口:
- 调用
self.infer(...)完成合成并计时; - 调用
postprocess(...)完成后处理; - 计算
duration(合成音频时长)与RTF(Real-Time Factor,infer_time / duration); - 返回
(lang, target_sample_rate, duration, wav_base64)。
该方法的日志输出(total inference time、RTF等)是评估离线 TTS 服务性能的直接依据。
三、配置文件:application.yaml 中的 tts_inference 段
离线推理引擎的配置段定义在 application.yaml 中,完整结构如下:
################### speech task: tts; engine_type: inference ####################### tts_inference: # am (acoustic model) choices=['speedyspeech_csmsc', 'fastspeech2_csmsc'] am: 'fastspeech2_csmsc' am_model: # the pdmodel file of your am static model (XX.pdmodel) am_params: # the pdiparams file of your am static model (XX.pdipparams) am_sample_rate: 24000 phones_dict: tones_dict: speaker_dict: spk_id: 0 am_predictor_conf: device: # set 'gpu:id' or 'cpu' switch_ir_optim: True glog_info: False # True -> print glog summary: True # False -> do not show predictor config # voc (vocoder) choices=['pwgan_csmsc', 'mb_melgan_csmsc','hifigan_csmsc'] voc: 'pwgan_csmsc' voc_model: # the pdmodel file of your vocoder static model (XX.pdmodel) voc_params: # the pdiparams file of your vocoder static model (XX.pdipparams) voc_sample_rate: 24000 voc_predictor_conf: device: # set 'gpu:id' or 'cpu' switch_ir_optim: True glog_info: False # True -> print glog summary: True # False -> do not show predictor config # others lang: 'zh'配置项含义如下:
| 配置项 | 说明 | 与源码的对应关系 |
|---|---|---|
am/voc | 声学模型与声码器名称,注释中给出的可选值即TTSServerExecutor支持范围 | 影响model_tag = am + '-' + lang的预训练模型下载 |
am_model/am_params/voc_model/voc_params | 静态模型文件路径,留空则自动下载预训练静态模型 | 传入_init_from_path,经os.path.abspath规范化 |
am_sample_rate/voc_sample_rate | 采样率,默认 24000;源码断言两者必须相等,否则初始化失败 | tts_engine.py |
phones_dict/tones_dict/speaker_dict | 音素/声调/说话人表 | 决定vocab_size、tone_size、spk_num |
spk_id | 默认说话人 ID | 请求级可覆盖 |
lang | zh或en | 决定使用中文Frontend还是英文English前端 |
am_predictor_conf/voc_predictor_conf | Predictor 配置 | 直接传入init_predictor |
am_predictor_conf/voc_predictor_conf的四个字段对应 paddle_predictor.py 的实现:
device:'gpu:id'或'cpu',为空时回退到paddle.get_device();含gpu时调用config.enable_use_gpu(1000, int(gpu_id))(1000 为显存缓存大小,单位 MB);switch_ir_optim:True时开启 IR 图优化;glog_info:False时调用config.disable_glog_info()屏蔽 Paddle Inference 的 glog 输出;summary:True时打印config.summary()展示 Predictor 配置摘要。
此外,无论配置如何,init_predictor都会调用config.enable_memory_optim()开启内存优化,并使用Config(model_file, params_file)以分离的模型/参数文件方式构造配置。
服务启动时需将engine_list配置为包含'tts_inference',例如:
host: 0.0.0.0 port: 8090 protocol: 'http' engine_list: ['tts_inference']配置文件头部注释明确列出了任务-引擎类型组合的合法取值:['asr_python', 'asr_inference', 'tts_python', 'tts_inference', 'cls_python', 'cls_inference'],tts_inference即离线 TTS 静态模型引擎。
四、REST 接口与请求参数
离线 TTS 引擎通过 tts_api.py 暴露 HTTP 接口。路由根据tts_engine.engine_type动态选择处理器:
if tts_engine.engine_type == "python": from paddlespeech.server.engine.tts.python.tts_engine import PaddleTTSConnectionHandler elif tts_engine.engine_type == "inference": from paddlespeech.server.engine.tts.paddleinference.tts_engine import PaddleTTSConnectionHandler即engine_type == "inference"时,请求会走本文所述的paddleinference模块。接口详情:
| 接口 | 方法 | 说明 |
|---|---|---|
/paddlespeech/tts/help | GET | 返回接口字段说明(text、audio) |
/paddlespeech/tts | POST | 离线合成,返回 base64 音频 |
请求体TTSRequest(定义于 request.py)字段与校验规则如下:
{ "text": "你好,欢迎使用百度飞桨语音合成服务。", "spk_id": 0, "speed": 1.0, "volume": 1.0, "sample_rate": 0, "save_path": "./tts.wav" }text:必填,待合成文本;spk_id:说话人 ID,默认0;speed:语速,默认1.0,合法范围0 < speed <= 3;volume:音量,默认1.0,合法范围0 < volume <= 3;sample_rate:目标采样率,默认0(保持模型采样率),仅允许0、8000、16000,超出将返回参数错误;save_path:音频保存路径,仅支持.wav与.pcm后缀。
参数校验在 tts_api.py 中完成,违规会返回SERVER_PARAM_ERR错误码。正常响应体中sample_rate为实际生效的目标采样率,duration为合成音频时长(秒),audio为 base64 编码的 WAV 数据。
五、端到端调用示例
仓库的 demos/speech_server 提供了客户端脚本,离线合成调用方式为:
paddlespeech_client tts --server_ip 127.0.0.1 --port 8090 --input "您好,欢迎使用百度飞桨语音合成服务。" --output output.wav若使用 curl 直接调用 REST 接口,等价请求为:
curl -X POST http://127.0.0.1:8090/paddlespeech/tts \ -H "Content-Type: application/json" \ -d '{"text": "您好,欢迎使用百度飞桨语音合成服务。", "spk_id": 0, "speed": 1.0, "volume": 1.0, "sample_rate": 16000, "save_path": "./output.wav"}'一次完整请求的处理时序为:REST 路由 → PaddleTTSConnectionHandler.run → TTSServerExecutor.infer(前端→AM Predictor→Vocoder Predictor)→ postprocess(重采样→调音量→变速→base64 编码/落盘),最终返回lang、target_sample_rate、duration与wav_base64。
六、源码级注意事项
- AM 与 Vocoder 采样率必须一致:
_init_from_path中assert voc_sample_rate == am_sample_rate,否则初始化直接失败(tts_engine.py)。 - 多说话人限制:注释明确"multi speaker do not have static model",
aishell3/vctk数据集的 fastspeech2 在静态推理时通过spk_id传入 AM 输入;请求级spk_id会覆盖配置文件默认值。 - 变速的依赖限制:
change_speed依赖 soxbindings,Windows 环境下不可用,异常分支会提示 "You need to set speed value 1.0"(tts_engine.py)。 - 性能观测点:服务日志中的
RTF由infer_time / duration计算得出,infer_time包含前端、AM、Vocoder 三段耗时(分别以frontend_time、am_time、voc_time记录),可用于定位瓶颈(tts_engine.py)。
七、与动态图引擎(python 类型)的差异
同为离线 TTS,tts_inference(静态模型)与tts_python(动态图)在 application.yaml 中的配置差异显著:
| 维度 | tts_inference | tts_python |
|---|---|---|
| 模型文件 | am_model/am_params(pdmodel/pdiparams) | am_config/am_ckpt/am_stat |
| 推理方式 | Paddle Inference Predictor(run_model) | 动态图(paddle.no_grad()下逐层执行) |
| 配置键 | am_predictor_conf/voc_predictor_conf | device、spk_id |
| 引擎类型标识 | inference | python |
两者在 REST 层共用TTSRequest与/paddlespeech/tts路由,仅通过engine_type区分处理器实现,因此业务侧无需感知引擎差异——这体现了服务端引擎池(engine_pool['tts'])按任务取引擎、按类型分发处理器的一致设计。
总结
paddlespeech.server.engine.tts.paddleinference是 PaddleSpeech 离线 TTS 服务中基于 Paddle Inference 静态模型的引擎实现:TTSServerExecutor负责静态模型资源加载与推理,TTSEngine负责引擎生命周期与设备管理,PaddleTTSConnectionHandler负责请求级的前后端处理与结果返回。通过 application.yaml 的tts_inference配置段即可完成部署,配合 tts_api.py 的 REST 接口与paddlespeech_client tts客户端即可快速验证效果。需要进一步自定义模型或调优时,可深入阅读 tts_engine.py 与 paddle_predictor.py 掌握 Predictor 封装细节。
- 人工智能
- 语音
- 音频
【免费下载链接】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.
相关推荐
PaddleSpeech TTS Paddle Inference 引擎深度解析:静态模型推理服务端的设计与实现
PaddleSpeech TTS Paddle Inference 引擎深度解析:静态模型推理服务端的设计与实现 PaddleSpeech 的服务端( padd
人工智能语音音频PaddleSpeech TTS 推理引擎源码解析:基于 Paddle Inference 的离线语音合成服务实现
PaddleSpeech TTS 推理引擎源码解析:基于 Paddle Inference 的离线语音合成服务实现 导读 本文以 PaddleSpeech 服务
人工智能语音音频NLP媒体生成PaddleSpeech 音频分类服务端推理引擎解析:PaddleCLSConnectionHandler 与 Paddle Inference 静态模型部署实现
PaddleSpeech 音频分类服务端推理引擎解析:PaddleCLSConnectionHandler 与 Paddle Inference 静态模型部署实
人工智能语音音频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考