跳转至

语音合成(TTS)技术分册 · 选型 / 部署 / 服务化

用途:为「跟读评测」服务提供朗读音源(TTS 朗读 → 用户跟读 → ASR+SOE 打分);同时作为中文 TTS 的选型依据与 CPU 部署操作手册,供 AI 助手直接照做。 环境:Windows Server 宿主机,2×Xeon Gold 6138(40 核 / 80 线程)、256GB 内存、F 盘 895G(剩余 862G);无独立 GPU,纯 CPU 推理。所有服务以 Docker 容器部署,产物只落 F:\EricLiu\,模型权重放 labs\models\。 版本基线:Piper v1.8.0(2026-09-04)|GPT-SoVITS 20250606v2pro(2025-06-06,主线另推 v2ProPlus / v4)|CosyVoice Fun-CosyVoice3-0.5B-2512|F5-TTS v1.1.22(2026-07-23)|Fish Speech / OpenAudio Drama 3(前代 S2-Pro 4B)|IndexTTS-2.5(2026-08-10)|ChatTTS v0.2.5(2026-04-10)|Speech-AI-Forge(聚合层,AGPL-3.0;最新 Windows 整合包 2026-02-02,更新日志持续至 2026-04)|edge-tts 7.3.1(2026-10-13,LGPL-3.0)|Kokoro-82M v1.0(2025-01-27)/ v1.1-zh(2025-02-26,独立中文权重)|MeloTTS v0.1.2(2024-03,MyShell/MIT)|OpenVoice v2(2024-04,MyShell/MIT;2025-04 后维护停滞)|bark(suno-ai,无 release,代码事实停更)|Spark-TTS-0.5B(2025-03,权重 CC-BY-NC-SA)|FireRedTTS-1S(小红书,2025-05 流匹配更新,代码 MPL-2.0 / 权重 Apache-2.0)(核对日期 2026-11-11,来源:官网/GitHub/HF/ModelScope)


0. 一页速查(AI 先读这段)

本机唯一能"实时"出声的只有 Piper。 其余模型在本机只能当离线批处理(一句几秒到几十秒),Fish Speech 直接不可行。

你要做的事 用哪个 一句话理由
跟读评测的朗读音源(EB1-1) Piper + zh_CN-huayan-medium CPU 实时、200ms 级延迟、模型 60MB、GPL 引擎但可自用
音色克隆(3-10 秒参考音频) GPT-SoVITS v2ProPlus 中文克隆效果最好,CPU RTF≈0.3-0.8(慢但能出)
多语言 / 方言 / 情绪指令 CosyVoice2/Fun-CosyVoice3-0.5B 覆盖 9 语种 + 18 方言,Apache-2.0,CPU 需 10 秒/句量级
英文自然度对比实验 F5-TTS 质量好,但 CPU 上是"泡咖啡"级速度
商用 / 生产 ❌ 除 Piper 外都不建议直接用 Piper 自用/内部服务可(GPL-3.0,对外分发闭源产品需评估);Fish Speech 权重非商用、ChatTTS AGPL+非商用、IndexTTS 自定义协议

三个硬约束(写进任何方案前先自查) 1. 无 GPU → 单句合成耗时按"Piper 0.1-0.5s / 其它 3-30s"预估,不要向用户承诺流式对话级体验。 2. 内存红线:同时开的容器合计 ≤150GB / 48 vCPU(宿主机 60%)。 3. 模型权重一律 F:\EricLiu\AppDocs\TTS\labs\models\,禁止落 C 盘用户目录。


1. 选型对比表

1.1 总表

项目 定位 中文支持 许可证 CPU 推理可行性(RTF 量级) 内存 / 模型体积 活跃度 推荐场景
Piper (OHF-Voice/piper1-gpl) 轻量 VITS + ONNX,边缘/嵌入 ✅ zh_CN-huayan-medium/x_low(espeak 音素);xia_ya 需 pinyin 音素,易踩坑 引擎 GPL-3.0-or-later;各音色单独授权(多为 MIT/CC) ✅✅ 实时。官方称树莓派 4 即实时;本机估算 RTF 0.01-0.05 <1GB / 单音色 20-80MB 活跃,v1.8.0(2026-09-04),但官方公开"寻找维护者" 跟读朗读源首选、批量配音、离线播报
GPT-SoVITS (RVC-Boss) 少样本克隆(5s 零样本 / 1min 微调) ✅✅ 最强中文克隆之一,含粤语 MIT ⚠️ 可跑但慢。官方 M4 CPU RTF 0.526;本机估算 0.3-0.8 6-10GB / 预训练权重约 3-4GB + G2PW 很活跃,tag 20250606v2pro,主线 v2ProPlus/v4 定制音色、有声书、离线批量克隆
CosyVoice (FunAudioLLM → QwenAudio) LLM 式 TTS,指令/方言/流式 ✅✅ 9 语种 + 18 方言,拼音纠音 Apache-2.0 ⚠️ 可跑(自动关掉 fp16/jit/trt/vllm);第三方 32 核实测 约 12.4s/句,估算 RTF 0.5-1.5 4-8GB / 0.5B ≈ 2-4GB 活跃但无 tag,最后提交 2026-05-25 多语言/方言、情绪与语速指令、GPU 场景
F5-TTS (SWivid) Flow-matching 扩散 Transformer,克隆 ✅ 中英(Emilia 训练) 代码 MIT / 权重 CC-BY-NC(非商用) ⚠️ 能跑,官方无 CPU 数据;估算 RTF 5-15 4-6GB / 1.35GB + Vocos 活跃,v1.1.22(2026-07-23) 英文自然度实验、GPU 场景克隆
Fish Speech / OpenAudio 商用级 Dual-AR / MoE ✅ 80+ 语种 代码 Apache-2.0 → 新版 Fish Audio Community/Research License;权重 CC-BY-NC-SA / 研究许可 ❌ 不可行。Drama 3 需 48GB 显存(FP8);S2-Pro 4B 亦需 GPU Drama 3 约 70GB 权重 很活跃(预发布节奏) 本机不用;仅作技术观察/云端 API
IndexTTS (B站 index-tts) 可导演情绪、语速、发音纠错 ✅✅ 中英日西阿,拼音/CMU/假名标注 B站自定义模型协议(商用需授权) ❌ 官方未声明 CPU 支持,全流程围绕 CUDA;估算 RTF 3-10 6-8GB / 0.8B ≈ 3-4GB + 辅助模型 活跃,IndexTTS-2.5(2026-08-10) 情绪化中文配音、短视频,GPU 场景
ChatTTS (2noise) 对话式口语化 TTS ✅ 中英 代码 AGPL-3.0 / 权重 CC-BY-NC ⚠️ 能跑;4090 上 RTF 0.3,CPU 估算 2-5 3-5GB / 约 1GB 缓慢维护,v0.2.5(2026-04-10),开源权重故意降质(MP3 压缩+高频噪声) 口语化/笑声停顿研究,禁商用
Kokoro (hexgrad/Kokoro-82M) 82M 轻量 StyleTTS 2 + ISTFTNet,单次前向(无扩散/自回归) ⚠️ v1.0 中文仅"部分支持"(misaki 前端弱);v1.1-zh 为独立权重(100 个中文音色,注音音素 + misaki[zh],官方标注"早期发布收集反馈") 权重 Apache-2.0 / 推理代码 MIT(espeak-ng 依赖 GPLv3) ✅✅ 第三方评测 CPU 约 5× 实时,显著快于 GPT-SoVITS/CosyVoice ~1GB / 82M ≈ 330MB(fp32),ONNX int8 约 80MB v1.0(2025-01-27)、v1.1-zh(2025-02-26,独立分支未并入主线);2026 生态仍活跃(NVIDIA ONNX 导出等) Piper 之外的自然度升级候选(CPU 可行的固定音色合成;上线前须按 EB1-1 实测中文质量)
MeloTTS (myshell-ai) VITS 系多语种 TTS,固定音色 ✅ 中文 + 中英混读(另有英式四口音/日/韩/法/西) MIT(代码+权重均 MIT) ✅✅ 官方称 CPU 快于实时(第三方 i7-12700 实测 RTF≈0.41) ~1GB / 约 180-300MB(按语种分装) 成熟稳定:v0.1.2(2024-03)后低频发版,代码库已定型 多语种/中英混读朗读;无克隆、无情绪控制,表达力低于大模型
OpenVoice v2 (myshell-ai) 两段式音色克隆(MeloTTS 基础合成 + 音色转换器),零样本跨语种 ✅ 中/英/日/韩/法/西原生 MIT(2024-04 起代码+权重均 MIT) ⚠️ 能跑但慢:音色提取模块默认 CUDA、CPU 无优化路径,估算 RTF >1 2-4GB / 基础 TTS + 转换器约 1GB 维护趋于停滞:最后实质提交 2025-04 MIT 全套干净的克隆备选;本机克隆仍首选 GPT-SoVITS(中文效果更好且更快)
bark (suno-ai) GPT 式音频语言模型(笑声/叹词/简单音乐) ✅ 含简中(13 语种) MIT ❌ CPU 不实用:3×300M 自回归逐 token 生成,小模型 + CPU offload 后仍以"几十秒-分钟/句"计 原生库 ~12GB 常驻;transformers fp16 权重 ~2GB 事实停更:代码最后实质提交 2023-09(README 最后修改 2024-08),从未发过 release,269 个 open issues;Suno 转向商业音乐产品 ❌ 回避本机部署;仅研究性试玩(权重 MIT 不会失效)
Spark-TTS (SparkAudio) LLM 式 TTS(Qwen2.5 骨干 + BiCodec 单流语音 token),零样本克隆 ✅ 中英双语 + 跨语种/混说 权重 CC-BY-NC-SA 4.0(2025-05 从 Apache-2.0 改约,禁商用);代码 Apache-2.0 ⚠️ 0.5B LLM 自回归,官方推理路径按 GPU 设计;CPU 估算 RTF 5-15,仅离线批处理 2-4GB / 0.5B ≈ 1.6GB(fp16) 推理代码发布后基本无大更新(2025 上半年后),仅推理无训练代码 ❌ 商用链路回避(权重改约禁商用);技术观察
FireRedTTS (小红书 FireRedTeam) 工业级流式 TTS 基座(1S 版,2025-05 加流匹配解码器) ✅✅ 中文自然度高(小红书自用同款) 代码 MPL-2.0 / 权重 Apache-2.0 ❌ 全流程按 CUDA 设计(安装文档只给 CUDA 版 torch),官方未声明 CPU 支持 4-8GB / 权重仓 11.75GB(ModelScope) FireRedTTS-1S(2025-05 技术报告+流匹配更新);已被 Speech-AI-Forge 聚合 ❌ 回避本机部署;仅作技术观察/云端方案

RTF = 合成耗时 / 音频时长。RTF<1 才是"快于实时"。表中"估算"为本机 40 核 Xeon 的量级推断,首次实测后请回来改成实测值(EB1-1 判据)。

1.2 许可证红线(比性能更容易翻车)

项目 代码 权重 商用结论
Piper GPL-3.0-or-later(wheel 内静态嵌入 espeak-ng) 音色各自授权,见仓库 docs/LICENSING.md 自用/内部服务无碍;对外分发闭源产品需评估 GPL,且逐个核对音色许可
GPT-SoVITS MIT MIT(自训权重更干净) ✅ 可商用(注意参考音频本身的权利)
CosyVoice Apache-2.0 Apache-2.0 ✅ 最宽松,首选做产品化验证
F5-TTS MIT CC-BY-NC(因 Emilia 数据集) ❌ 权重不可商用
Fish Speech Apache-2.0(旧)/ 自定义(新) CC-BY-NC-SA / 研究许可 ❌ 商用需单独书面协议
IndexTTS B站协议 同 ⚠️ 商用需联系 indexspeech@bilibili.com
ChatTTS AGPL-3.0 CC-BY-NC ❌ 双重不友好
Kokoro MIT(推理代码) Apache-2.0 ✅ 可商用(espeak-ng 依赖为 GPLv3,容器分发时注意合规;v1.1-zh 中文数据来自 LongMaoData 授权,同样 Apache-2.0)
MeloTTS MIT MIT ✅ 可商用
OpenVoice v2 MIT MIT ✅ 可商用(注意参考音频本身的权利)
bark MIT MIT ✅ 许可最宽松,但已停更 + CPU 不实用,许可好不等于能用
Spark-TTS Apache-2.0(代码) CC-BY-NC-SA 4.0(2025-05 改约) ❌ 权重禁商用,衍生作品须同协议
FireRedTTS MPL-2.0 Apache-2.0 ⚠️ 权重可商用,但 CUDA 导向、CPU 无官方路径(本机回避)

1.3 选型决策树

需要"实时/低延迟"出声? ── 是 ──> Piper(唯一答案)
        │
        否
        ↓
需要克隆某个特定人声? ── 是 ──> 中文优先 GPT-SoVITS;多语种/方言优先 CosyVoice
        │
        否
        ↓
只要"好听、像播音"? ──> 先用 Piper huayan 试听,不满意再上 CosyVoice(Apache 最安全)

1.4 整合/聚合型项目(推荐与回避)

推荐逻辑:TTS 起步一律 Piper 直连(§3.3 内置 HTTP 或 §4 自封装,无中间层、延迟最低)。聚合层只在两种情况下引入:① 需要 ChatTTS/CosyVoice/GPT-SoVITS 等多引擎统一 HTTP 面板;② 需要 SSML/长文本切分/多角色播客这类"重前端工作流",用现成聚合省去自研封装。被聚合引擎的许可证会逐层叠加,商用前必须逐个核对。

项目 定位 维护状态 许可证 CPU 可行性 结论:推荐用/选配/回避
Speech-AI-Forge (lenML) 多引擎 TTS/ASR 聚合服务:API Server(:7870,OpenAPI 文档 /docs)+ Gradio WebUI;SSML/长文本分割/播客/音色管理 活跃:2026-04 仍在新增后端(260402 接入 MiniMax 云 TTS);最新 Windows 整合包 2026-02-02 AGPL-3.0(网络服务需开源修改;本库自用无碍) ⚠️ 是封装层,CPU 可行性=被聚合引擎的可行性:本机可跑 ChatTTS/CosyVoice/GPT-SoVITS(离线级速度),FishSpeech/IndexTTS 系不可行 选配:需要多引擎统一入口或 SSML/播客工作流时用,省去自研多引擎封装;注意其聚合列表是 ChatTTS/CosyVoice2-3/F5-TTS/GPT-SoVITS/FireRedTTS/Index-TTS/Qwen3-TTS/Spark-TTS/FishSpeech + MiniMax 云 TTS,不含 EdgeTTS 与 Piper——日常朗读仍走 Piper 直连
edge-tts (rany2) 调用微软 Edge"大声朗读"在线神经语音的 Python 库 活跃,v7.3.1(2026-10-13) LGPL-3.0(代码);语音本身无商用授权 ✅ 本地零推理开销,但依赖外网 回避(进生产链路):走微软非官方接口——Microsoft 服务协议未对 Read Aloud 语音授予商用权(官方 Q&A 2026-06-22 答复确认无公开商用授权文档),无 SLA、接口随时可能变更/封禁;仅可作临时试听、与本地音色做对比参考。生产音源一律用本地 Piper/其它自托管引擎

1.5 推荐结论(一句话版)

  • 首选 = Piper(zh_CN-huayan-medium):本机唯一能实时出声的引擎(RTF 0.01-0.05、单音色 20-80MB、200ms 级响应),跟读朗读源的标准答案;GPL-3.0 引擎自用/内部服务无碍,对外分发闭源产品再评估。
  • 选配 = Speech-AI-Forge(AGPL-3.0):仅在需要多引擎统一 HTTP 面板或 SSML/长文本/播客工作流时引入(其聚合列表不含 Piper 与 EdgeTTS,日常朗读仍走 Piper 直连);克隆加 GPT-SoVITS(MIT,CPU 慢速可用)、多语种/方言加 CosyVoice(Apache-2.0)。
  • 回避 = edge-tts 进生产(微软非官方 Read Aloud 接口,无商用授权、无 SLA、随时变更/封禁);F5-TTS 权重(CC-BY-NC)、ChatTTS(AGPL+CC-BY-NC)、Fish Speech(研究许可/需 48GB 显存)、IndexTTS(B站协议)在商用链路一律回避,只作技术观察。
  • 2026-11 扩充(CPU 小模型候选与新增回避):
  • 选配候选 = Kokoro(82M,Apache-2.0)/ MeloTTS(MIT):两者均为 CPU 友好的固定音色 TTS(Kokoro 第三方评测 CPU 约 5× 实时;MeloTTS 官方称快于实时),是"Piper 音色不够自然、又不想上 GPT-SoVITS/CosyVoice 级耗时"时的中间档;中文分别依赖 v1.1-zh 独立权重与内置中文模型,上线前必须按 EB1-1 先单句实测。
  • 新增回避:bark(代码事实停更于 2023-09 + 3×300M 自回归 CPU 不实用)、Spark-TTS(权重 2025-05 由 Apache-2.0 改为 CC-BY-NC-SA 禁商用)、FireRedTTS(安装与推理全流程 CUDA 导向,CPU 无官方路径)、OpenVoice v2(CPU 慢 + 2025-04 后维护停滞;其 MIT 全套干净的优势在 GPU 环境才体现,本机克隆仍首选 GPT-SoVITS)。

2. 安装部署

2.1 Piper 安装(三选一)

方式 A:pip(最快验证,Windows 宿主机直接跑)

python -m venv F:/EricLiu/Envs/piper
F:/EricLiu/Envs/piper/Scripts/activate

pip install piper-tts            # 引擎(自带 espeak-ng 数据,无需系统装 espeak-ng)
pip install "piper-tts[http]"    # 需要内置 HTTP 服务时

# 列音色 / 下音色(默认下到当前目录,用 --data-dir 指定)
python -m piper.download_voices
python -m piper.download_voices zh_CN-huayan-medium --data-dir F:/EricLiu/AppDocs/TTS/labs/models/piper

国内下载卡住时:

export HF_ENDPOINT=https://hf-mirror.com
python -m piper.download_voices zh_CN-huayan-medium --data-dir F:/EricLiu/AppDocs/TTS/labs/models/piper

音色选择坑:中文只有 zh_CN-huayan-medium / zh_CN-huayan-x_low 是标准 espeak 音素,开箱即用。zh_CN-xia_ya-* 用的是拼音音素集,缺 g2pW 时会大量报 Parsing phonemes failed。先用 huayan。

方式 B:Docker(推荐,服务化基线)

见 §4.2 的 docker-compose.yml。

方式 C:二进制

官方仅提供 Linux amd64/arm64/armv7 预编译包(piper_amd64.tar.gz)。Windows 宿主机不适用,请用方式 A 或 B。

2.2 Piper 目录约定

F:\EricLiu\AppDocs\TTS\
├── README.md                      ← 本文件
├── docker\tts-piper\              ← Dockerfile + compose + app
└── labs\
    ├── models\piper\              ← zh_CN-huayan-medium.onnx + .onnx.json
    └── EB1-1-first-wav\           ← 实验产物(wav + 报告)

2.3 GPT-SoVITS(CPU 跑通路径,诚实提示:慢)

CPU 能跑,但只适合离线批量:一句 10 秒音频约 3-8 秒出(v2ProPlus,40 核),比 Piper 慢两个数量级。

# 1) 只要 CPU 环境,安装时显式指定 CPU(不要装 CUDA 版 torch)
conda create -n GPTSoVits python=3.10 -y && conda activate GPTSoVits
git clone https://github.com/RVC-Boss/GPT-SoVITS.git F:/EricLiu/AppDocs/TTS/labs/src/GPT-SoVITS
cd F:/EricLiu/AppDocs/TTS/labs/src/GPT-SoVITS
bash install.sh --device CPU --source HF-Mirror   # Windows 用: pwsh -F install.ps1 --Device CPU --Source HF-Mirror

# 2) 权重放到 GPT_SoVITS/pretrained_models(约 3-4GB)
#    v2Pro / v2ProPlus 权重 + 中文必备 G2PWModel → GPT_SoVITS/text/G2PWModel

# 3) 启动 API(比 WebUI 更适合服务化)
python api_v2.py -a 127.0.0.1 -p 9880 -c GPT_SoVITS/configs/tts_infer.yaml

CPU 下的必要动作: - 推理前确认 is_half: false(半精度在 CPU 上无意义,还可能报错)。 - 设 OMP_NUM_THREADS=16(别开 80,OpenMP 超线程反而抖动)。 - 参考音频 3-10 秒、干净单人、无 BGM;先用 UVR5 去伴奏再切片。 - 长文本按句切分后串行合成,避免一次性显存/内存峰值。

2.4 CosyVoice(CPU 跑通路径)

CosyVoice 的推理封装会在检测不到 CUDA 时自动把 load_jit/load_trt/load_vllm/fp16 全置 False 并打印 no cuda device... 警告——这是正常现象,说明已回退到 CPU。

git clone --recursive https://github.com/FunAudioLLM/CosyVoice.git F:/EricLiu/AppDocs/TTS/labs/src/CosyVoice
cd F:/EricLiu/AppDocs/TTS/labs/src/CosyVoice
conda create -n cosyvoice python=3.10 -y && conda activate cosyvoice

# 关键:先装 CPU 版 torch,再装依赖,否则会拖进来 2GB+ 的 CUDA 轮子
pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements.txt

# 权重(二选一,国内优先 ModelScope)
python -c "from modelscope import snapshot_download; snapshot_download('iic/CosyVoice2-0.5B', local_dir='pretrained_models/CosyVoice2-0.5B')"

CPU 下的调用参数(务必显式关加速):

from cosyvoice.cli.cosyvoice import CosyVoice2
cosy = CosyVoice2('pretrained_models/CosyVoice2-0.5B',
                  load_jit=False, load_trt=False, load_vllm=False, fp16=False)

依赖地狱预警:sox / ttsfrd / WeTextProcessing 任一缺失都可能让文本前端报错;pip install -r requirements.txt 失败时优先查 Python 版本(必须 3.10)与 torch 是否被 CUDA 版覆盖。

2.5 不建议在本机安装的几个

  • Fish Speech:Drama 3 需 ≥48GB 显存(FP8),S2-Pro 为 4B+400M 双 AR,CPU 上单句以"分钟"计。结论:本机不装,需要时走官方 API。
  • IndexTTS-2.5:仓库全部流程按 CUDA 设计(tools/gpu_check.py、CUDA 12.8、deepspeed),未声明 CPU 支持。装了大概率卡在编译 kernel。
  • bark(2026-11 补充核实):代码事实停更(最后实质提交 2023-09),3×300M 自回归 + EnCodec,CPU 上"几十秒-分钟/句";原生库要 ~12GB 常驻。不值得装。
  • Spark-TTS / FireRedTTS(2026-11 补充核实):前者权重 CC-BY-NC-SA 禁商用且官方路径按 GPU 设计;后者 CUDA 导向、权重仓 11.75GB、未声明 CPU 支持。均回避。

3. 高频用法

3.1 Piper 命令行

# 基础:stdin 文本 → wav(-m 音色名,-f 输出文件,-- 分隔)
python -m piper -m zh_CN-huayan-medium \
  --data-dir F:/EricLiu/AppDocs/TTS/labs/models/piper \
  -f F:/EricLiu/AppDocs/TTS/labs/EB1-1-first-wav/hello.wav \
  -- '你好,这是一段中文语音合成测试。'

# 从文件读入(批量)
python -m piper -m zh_CN-huayan-medium --input-file sentences.txt --output-dir out/

# 常用开关
#   --cuda              启用 GPU(本机无效,需 onnxruntime-gpu)
#   --sentence-silence  句间静音秒数(默认偏短,朗读评测建议 0.2)
#   --volume            音量倍数;--no-normalize 关闭自动归一化
#   --output-raw        输出裸 PCM(流式场景)

CLI 每次都要重新加载模型(约 0.1-0.5s),批量合成请用 HTTP 服务或 Python 常驻进程。

注音注入(多音字兜底):Piper 支持 espeak 音素直写

他在银 [[ j ǐ n ]] 行里行走。      # 用 espeak-ng -v cmn --ipa=3 -q 银行 先查出音素

3.2 Piper Python API

import wave
from piper import PiperVoice

# 1.7+ 的用法:load 一次,反复 synthesize(务必复用对象)
voice = PiperVoice.load(
    "F:/EricLiu/AppDocs/TTS/labs/models/piper/zh_CN-huayan-medium.onnx"
)

with wave.open("out.wav", "wb") as wav:
    voice.synthesize_wav("你好,世界。", wav)

控制语速/随机度(1.7+ 用 SynthesisConfig):

from piper import PiperVoice, SynthesisConfig

cfg = SynthesisConfig(length_scale=1.15, noise_scale=0.667, noise_w_scale=0.8)
with wave.open("slow.wav", "wb") as wav:
    voice.synthesize_wav("慢一点读。", wav, syn_config=cfg)

length_scale > 1 变慢,< 1 变快;跟读场景建议 1.0-1.15(太慢会破坏韵律,SOE 打分反而失真)。

3.3 内置 HTTP 服务(零代码起步)

pip install "piper-tts[http]"
python -m piper.http_server -m zh_CN-huayan-medium --host 0.0.0.0 --port 5000 \
  --data-dir F:/EricLiu/AppDocs/TTS/labs/models/piper
curl localhost:5000/info
curl localhost:5000/voices
curl -X POST -H 'Content-Type: application/json' \
     -d '{"text":"你好","length_scale":1.1}' \
     -o out.wav localhost:5000/synthesize

字段:text(必填)、voice、speaker/speaker_id、length_scale、noise_scale、noise_w_scale。缺省回落到启动参数 → 音色配置。

3.4 GPT-SoVITS API

curl -X POST http://127.0.0.1:9880/tts -H "Content-Type: application/json" -d '{
  "text": "要合成的中文文本",
  "text_lang": "zh",
  "ref_audio_path": "F:/EricLiu/AppDocs/TTS/labs/ref/voice.wav",
  "prompt_text": "参考音频里说的那句话",
  "prompt_lang": "zh",
  "speed_factor": 1.0,
  "streaming_mode": false
}' --output out.wav

prompt_text 必须与参考音频逐字一致,否则音色漂移。api_v2.py 文件头部 docstring 是完整字段说明。

3.5 CosyVoice Python(零样本克隆)

import torchaudio
from cosyvoice.cli.cosyvoice import CosyVoice2

cosy = CosyVoice2('pretrained_models/CosyVoice2-0.5B',
                  load_jit=False, load_trt=False, load_vllm=False, fp16=False)

for i, out in enumerate(cosy.inference_zero_shot(
        '要合成的文本。', '参考音频对应的文本。', 'ref.wav', stream=False)):
    torchaudio.save(f'out_{i}.wav', out['tts_speech'], cosy.sample_rate)

首次调用会触发模型加载(CPU 上 20-60s),服务化时必须做"启动预热 + 常驻单例"。


4. 服务化:FastAPI 封装 Piper(EB1-2)

为什么还要自己包一层:内置 http_server 没有 /health(HAProxy/Keepalived 探活要用)、没有统一错误码、不方便加缓存与鉴权、也不便与 ASR/SOE 共用一套响应格式。

4.1 目录结构

F:\EricLiu\AppDocs\TTS\docker\tts-piper\
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── app\
    └── main.py

4.2 docker-compose.yml

services:
  tts-piper:
    build: .
    image: local/tts-piper:1.8.0
    container_name: tts-piper
    restart: unless-stopped
    ports:
      - "8101:8000"
    environment:
      PIPER_DATA_DIR: /models
      PIPER_VOICE: zh_CN-huayan-medium
      OMP_NUM_THREADS: "8"          # 单容器别超 8,靠多副本横向扩
    volumes:
      - "F:/EricLiu/AppDocs/TTS/labs/models/piper:/models:ro"
    deploy:
      resources:
        limits:
          cpus: "8"
          memory: 4G
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request;urllib.request.urlopen('http://127.0.0.1:8000/health')"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

4.3 Dockerfile

FROM python:3.12-slim

# onnxruntime 依赖 libgomp1;piper wheel 已自带 espeak-ng 数据,无需装 espeak-ng
RUN apt-get update && apt-get install -y --no-install-recommends libgomp1 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app/ ./app/
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]

requirements.txt:

piper-tts==1.8.0
fastapi==0.115.*
uvicorn[standard]==0.32.*

固定版本号:Piper 1.x 的 Python API 在小版本间改过(synthesize → synthesize_wav + SynthesisConfig),不锁版本迟早踩坑。 --workers 1:模型是进程内对象,多 worker 会复制内存;要并发就多开容器。

4.4 app/main.py(完整可跑,含 /health)

import io
import os
import threading
import time
import wave

from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel, Field
from piper import PiperVoice

try:                          # piper-tts >= 1.7
    from piper import SynthesisConfig
except ImportError:           # 1.2.x 分支
    SynthesisConfig = None

DATA_DIR = os.getenv("PIPER_DATA_DIR", "/models")
DEFAULT_VOICE = os.getenv("PIPER_VOICE", "zh_CN-huayan-medium")
STARTED_AT = time.time()

app = FastAPI(title="Piper TTS API", version="1.0.0")

_voices: dict[str, PiperVoice] = {}
_lock = threading.Lock()


def get_voice(name: str) -> PiperVoice:
    """懒加载 + 复用。加载耗时 0.1-0.5s,不可每次请求新建。"""
    with _lock:
        if name not in _voices:
            path = os.path.join(DATA_DIR, f"{name}.onnx")
            if not os.path.exists(path):
                raise FileNotFoundError(f"voice not found: {path}")
            _voices[name] = PiperVoice.load(path)
        return _voices[name]


class TTSRequest(BaseModel):
    text: str = Field(..., min_length=1, max_length=2000)
    voice: str | None = None
    length_scale: float = Field(1.0, ge=0.5, le=2.0)
    speaker_id: int | None = None


@app.get("/health")
def health():
    return {
        "status": "ok",
        "engine": "piper",
        "default_voice": DEFAULT_VOICE,
        "loaded_voices": sorted(_voices),
        "uptime_sec": round(time.time() - STARTED_AT, 1),
    }


@app.get("/voices")
def voices():
    """列出 /models 下已下载的音色(.onnx 与 .onnx.json 成对才算)。"""
    items = []
    if os.path.isdir(DATA_DIR):
        for f in sorted(os.listdir(DATA_DIR)):
            if f.endswith(".onnx"):
                name = f[:-5]
                items.append({"name": name,
                              "ready": os.path.exists(os.path.join(DATA_DIR, f + ".json"))})
    return {"data_dir": DATA_DIR, "voices": items}


@app.post("/synthesize")
def synthesize(req: TTSRequest):
    name = req.voice or DEFAULT_VOICE
    try:
        voice = get_voice(name)
    except FileNotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    buf = io.BytesIO()
    t0 = time.perf_counter()
    try:
        with wave.open(buf, "wb") as wf:
            cfg = None
            if SynthesisConfig is not None:
                cfg = SynthesisConfig(
                    length_scale=req.length_scale,
                    speaker_id=req.speaker_id,
                )
            if hasattr(voice, "synthesize_wav"):
                if cfg is not None:
                    voice.synthesize_wav(req.text, wf, syn_config=cfg)
                else:
                    voice.synthesize_wav(req.text, wf)
            else:
                voice.synthesize(req.text, wf)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"synthesis failed: {e}")

    cost = time.perf_counter() - t0
    data = buf.getvalue()
    return Response(
        content=data,
        media_type="audio/wav",
        headers={
            "X-Voice": name,
            "X-Synth-Seconds": f"{cost:.3f}",
            "X-Audio-Bytes": str(len(data)),
        },
    )

启动后自检:

docker compose up -d --build
curl -s localhost:8101/health
curl -s -X POST localhost:8101/synthesize -H "Content-Type: application/json" \
     -d '{"text":"你好,欢迎使用跟读评测服务。"}' -o hello.wav
ffprobe hello.wav           # 看时长是否与文本匹配

验收判据(EB1-2):/health 返回 200;合成 wav 可播放;响应头 X-Synth-Seconds / 音频时长 得到 RTF;容器 healthy。


5. 排障速查

现象 根因 处理
Parsing phonemes failed for ... 音色与音素集不匹配(xia_ya 需 pinyin/g2pW) 换 zh_CN-huayan-medium;或装 piper-tts[zh]
合成出来是静音/极短 .onnx 与 .onnx.json 不配套或 json 缺失 两文件必须同名同目录
首次请求 5xx,之后正常 懒加载超时 / 并发首次加载 启动后预热一句;_lock 已串行化,或加 start_period
ImportError: libgomp.so.1 slim 镜像缺 OpenMP apt install libgomp1
下载音色超时 HF 不可达 HF_ENDPOINT=https://hf-mirror.com,或手动下载两文件放入 --data-dir
中文读音怪 / 多音字错 espeak 前端局限 用 [[ 音素 ]] 强制注音;或改用 GPT-SoVITS/CosyVoice
合成速度慢 CLI 每次加载模型 / OMP 线程过多 用常驻服务;OMP_NUM_THREADS=8 左右
音色像"念稿机" Piper 本身就是轻量 VITS 属预期;跟读场景可接受,追求自然度换模型
GPT-SoVITS 报 G2PW 相关错 中文前端模型没放对 解压为 GPT_SoVITS/text/G2PWModel
CosyVoice no cuda device, set load_... to False 正常回退 忽略;不要试图在 CPU 上开 fp16
容器 OOM 多副本 + 大模型 单容器限 4G,副本数按 free -g 规划

6. AI 操作守则(本分册强制)

  1. 先确认体积再下载。任何 snapshot_download / hf download 之前,告诉用户:仓库名、总体积(Piper 音色 20-80MB;GPT-SoVITS 3-4GB;CosyVoice 2-4GB;F5-TTS 1.4GB)、落盘路径、预估耗时,等确认再执行。
  2. 长任务一律后台跑。合成超过 30 秒、模型下载、权重转换,都用后台任务并定期汇报进度;不要阻塞对话。
  3. CPU 耗时诚实预告。启动任何非 Piper 的合成前,先给"预计 X 秒/句",禁止说"很快"。
  4. 单句先验证再批量。批量合成前先跑 1 句,检查时长(ffprobe)与听感,再放大到 N 句。
  5. 不改系统环境。不 pip install 到全局、不动 C 盘、不改 PATH;一律 venv 或容器。
  6. 许可证先查后用。推荐任何模型前先看 §1.2;商用场景默认推 CosyVoice(Apache-2.0)/ GPT-SoVITS(MIT),禁推 F5-TTS 权重与 ChatTTS。
  7. 不代注册、不代充值。Fish Speech / 讯飞 / 腾讯云等只做能力说明。
  8. 产物落盘有规矩:音频进 labs\E*XX-*\,权重进 labs\models\,临时文件进 F:\EricLiu\tmp\,并在实验报告里引用具体文件名。
  9. 端口登记:TTS 用 8101(保留 8100 给网关),Piper 内置服务 5000,GPT-SoVITS 9880,CosyVoice WebUI 50000。新占端口先查冲突。
  10. 失败即记录。踩坑与解决方式同步到 AppDocs\Reusable\,避免同一坑踩两次。

7. 参考链接与更新记录

  • Piper:https://github.com/OHF-Voice/piper1-gpl | CLI/HTTP/Python 文档见 docs/ | 音色试听 https://rhasspy.github.io/piper-samples
  • 旧仓库(已归档,MIT):https://github.com/rhasspy/piper
  • 音色库:https://huggingface.co/rhasspy/piper-voices
  • GPT-SoVITS:https://github.com/RVC-Boss/GPT-SoVITS
  • CosyVoice:https://github.com/FunAudioLLM/CosyVoice (现重定向至 QwenAudio/CosyVoice)
  • F5-TTS:https://github.com/SWivid/F5-TTS
  • Fish Speech / OpenAudio:https://github.com/fishaudio/fish-speech
  • IndexTTS:https://github.com/index-tts/index-tts
  • ChatTTS:https://github.com/2noise/ChatTTS
  • Speech-AI-Forge:https://github.com/lenML/Speech-AI-Forge
  • edge-tts:https://github.com/rany2/edge-tts | PyPI https://pypi.org/project/edge-tts/
  • Kokoro:https://huggingface.co/hexgrad/Kokoro-82M | 中文权重 https://huggingface.co/hexgrad/Kokoro-82M-v1.1-zh | 推理库 https://github.com/hexgrad/kokoro
  • MeloTTS:https://github.com/myshell-ai/MeloTTS
  • OpenVoice:https://github.com/myshell-ai/OpenVoice
  • bark:https://github.com/suno-ai/bark
  • Spark-TTS:https://github.com/SparkAudio/Spark-TTS | 权重 https://huggingface.co/SparkAudio/Spark-TTS-0.5B
  • FireRedTTS:https://github.com/FireRedTeam/FireRedTTS | 权重 https://modelscope.cn/models/FireRedTeam/FireRedTTS-1S
日期 变更
2026-11-11 建档:7 个项目版本基线核对、选型表、Piper 部署与服务化模板、CPU 可行性评估
2026-11-11 新增 §1.4 整合/聚合型项目:Speech-AI-Forge(选配,AGPL-3.0)、edge-tts(回避生产,LGPL-3.0+微软非官方接口风险);版本基线补充
2026-11-11 选型表扩充 6 行(联网核实):Kokoro(82M,Apache-2.0,CPU 约 5× 实时,中文走 v1.1-zh 独立权重,选配候选)、MeloTTS(MIT,CPU 快于实时,选配候选)、OpenVoice v2(MIT 但 CPU 慢+维护停滞)、bark(事实停更 2023-09,CPU 不实用,回避)、Spark-TTS(权重 2025-05 改约 CC-BY-NC-SA 禁商用,回避)、FireRedTTS-1S(MPL-2.0/Apache-2.0,CUDA 导向,回避);§1.2 许可证表、§2.5、§1.5 同步;版本基线补充