目录

端侧语音合成实战:用 Piper 让应用离线开口说话

为什么要在端侧跑语音合成

上一篇《端侧语音识别实战》解决了"听懂",这篇解决"说话"。语音合成(TTS)同样有云端方案解决不了的问题:儿童故事机、导航提示、无障碍朗读、本地语音助手,要么没网,要么把文本上传云端合成既花钱又泄露内容——刚输入的文字、个人笔记、聊天记录都是敏感数据。

端侧 TTS 的思路和端侧 ASR 一致:把模型压缩到几十 MB,直接在设备 CPU 上合成。2026 年的当下,Piper 是这条赛道上最成熟的选手。

Piper 是什么

Piper 是一个本地神经网络 TTS 引擎:

  • 模型用 VITS 架构训练,导出成 ONNX,用 onnxruntime 推理,不依赖 GPU
  • 文本转音素用 espeak-ng,因此支持 40 多种语言,包括简体中文
  • 每个音色只需两个文件:一个 .onnx 模型(几十 MB)加一个 .onnx.json 配置

维护现状(2026 年核实):原仓库 rhasspy/piper 已归档,开发迁移到 Open Home Foundation 维护的 OHF-Voice/piper1-gpl(Home Assistant、NVDA 屏幕阅读器都在用它),安装方式不变:

1
pip install piper-tts

音色从 Hugging Face 的 rhasspy/piper-voices 仓库下载,中英文各推荐一个典型音色:

  • en_US-lessac-medium:英文,onnx 文件约 63 MB
  • zh_CN-huayan-medium:中文,onnx 文件约 100 MB(具体大小以仓库实际为准)

三分钟跑通 CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 下载音色(模型 + 配置两个文件都要)
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/lessac/medium/en_US-lessac-medium.onnx
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/lessac/medium/en_US-lessac-medium.onnx.json

# 一句话合成
echo 'Welcome to the world of speech synthesis!' | \
  piper --model en_US-lessac-medium.onnx --output_file welcome.wav

# 中文 + 调速(length_scale 越大越慢,默认 1.0)
echo '你好,我是运行在你设备上的语音助手。' | \
  piper --model zh_CN-huayan-medium.onnx --length_scale 1.1 --output_file hello.wav

Python 集成:几行代码合成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from piper import PiperVoice

voice = PiperVoice.load("zh_CN-huayan-medium.onnx")

# 合成到 WAV 文件
voice.synthesize("离线合成,音频不出设备。", "hello.wav")

# 也可以合成进文件对象,方便接播放库
with open("hello.wav", "wb") as f:
    voice.synthesize("故事机该给孩子讲什么?", f)

PiperVoice.load 会初始化好 onnxruntime 推理会话,之后每次合成都是纯 CPU 计算,无网络请求。批量文本逐句调用即可;多线程调用时注意控制 onnxruntime 的线程数(num_threads),避免抢满 CPU 导致应用其他任务卡顿。

中文合成踩坑

espeak-ng 的音素化对中文支持有限,数字、英文、符号混排时读音会怪。最简单的兜底方案:合成前做一次文本规范化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import re

digit_map = {"0": "零", "1": "一", "2": "二", "3": "三", "4": "四",
             "5": "五", "6": "六", "7": "七", "8": "八", "9": "九"}

def normalize_zh(text: str) -> str:
    # 简单方案:阿拉伯数字先转中文,espeak-ng 读中文数字更稳
    return re.sub(r"\d", lambda m: digit_map[m.group(0)], text)

print(normalize_zh("3月5日"))  # 输出:三月五日

这个方案只处理数字,遇到"3G、5G"这类词要加白名单,正式产品建议直接用专门的中文文本正则化库。

给其他进程提供合成接口

Piper 自带 HTTP 服务,可以给 Flutter、Electron 等其他技术栈的进程提供合成接口:

1
2
python3 -m piper.http_server --model en_US-lessac-medium.onnx --port 5000
curl -s 'http://127.0.0.1:5000/synthesize?text=hello' -o out.wav

性能与选型

Piper 官方定位是 fast local。社区实测(非官方数据):x86 桌面 CPU 上 medium 音色通常数倍于实时,树莓派 4 这类弱设备上 medium 接近实时、small 音色可超实时。对提示音、朗读这类场景完全够用。

项目 定位 一句话
Piper(piper1-gpl) 端侧轻量 TTS 本文主角,VITS + espeak-ng,几十 MB 模型,CPU 实时,Home Assistant 内置
sherpa-onnx 端侧语音全家桶 上一篇的主角,ASR 为主也带 TTS,适合与识别统一框架
Kokoro 高音质本地 TTS 82M 参数,音质接近商用水平,适合内容生成场景
edge-tts 在线免费 TTS 微软 Edge 朗读接口封装,音质好但要联网
CosyVoice / F5-TTS 本地大 TTS 支持音色克隆、表现力强,需要 GPU 或高端设备

小结

Piper 把离线语音合成做到了几十 MB 模型、纯 CPU、中文可用的程度。和 sherpa-onnx 组合,就能在自有设备上搭一套完整语音对话闭环:麦克风进来(ASR)到扬声器出去(TTS)全程零网络请求。对医疗、教育、个人助手这类隐私敏感场景,这是实打实的卖点。