一、背景
在机器人、IoT、智能语音播报、局域网设备等场景中,经常需要:
本地化 TTS(Text To Speech)
离线运行
低延迟
不依赖云服务
可控的音频编码格式
可二次开发
目前较流行的开源方案中,Coqui TTS 官方仓库 是一个成熟度较高的本地 TTS 引擎。
其特点:
支持多语言
支持中文
支持 Docker
支持 REST API
支持 CPU/GPU
支持自定义模型
Python 可扩展性强
本文基于:
ghcr.io/coqui-ai/tts-cpu二、基础部署
1. 拉取镜像
docker pull ghcr.io/coqui-ai/tts-cpu2. 启动容器
docker run -d \
--name coqui-tts \
-p 5002:5002 \
-v /opt/tts-model:/root/.local/share/tts \
--restart unless-stopped \
--entrypoint python3 \
ghcr.io/coqui-ai/tts-cpu \
TTS/server/server.py \
--model_name tts_models/zh-CN/baker/tacotron2-DDC-GST三、模型缓存目录说明
参数:
-v /opt/tts-model:/root/.local/share/tts含义:
作用:
模型持久化
避免重复下载
方便备份
支持离线部署
四、HTTP API 调用
默认接口:
GET /api/tts示例:
curl "http://localhost:5002/api/tts?text=你好"返回:
audio/wav默认是:
WAV
PCM
无压缩
五、为什么需要二次扩展
虽然默认 API 可用,但实际生产环境会遇到几个问题。
1. WAV 文件过大
默认:
16bit PCM WAV文件体积很大。
例如:
对于:
MQTT
机器人
4G网络
IoT
非常不友好。
2. 不支持 MP3 / OPUS
默认只输出:
audio/wav不支持:
MP3
OPUS
AAC
3. 无法控制码率
默认:
无法控制 bitrate
无法控制采样率
无法控制声道
六、几种扩展方案对比
方案一:客户端转码
架构:
Coqui -> WAV -> 客户端 ffmpeg -> MP3优点
不改服务端
简单
缺点
客户端负担重
网络传输大
不适合 IoT
方案二:Nginx/OpenResty 转码
架构:
Coqui -> WAV -> Nginx/OpenResty -> ffmpeg -> MP3优点
不改 Coqui
网关统一处理
缺点
Lua 较复杂
调试困难
临时文件管理复杂
高并发容易出问题
方案三:Java 服务转码
架构:
客户端
↓
Java API
↓
Coqui TTS
↓
ffmpeg-java
↓
MP3/OPUS优点
易扩展
易做缓存
易做权限控制
缺点
服务链路更长
增加维护复杂度
方案四:直接扩展 server.py(最终选择)
架构:
客户端
↓
Coqui server.py
↓
ffmpeg
↓
MP3/OPUS优点
1. 改动最小
只修改:
/root/TTS/server/server.py2. 无额外服务
无需:
Nginx Lua
Java 转码层
独立 ffmpeg 服务
3. 性能最好
避免:
多次 HTTP
多次磁盘 IO
多进程链路
4. 最适合局域网机器人
尤其:
MQTT
IoT
边缘设备
本地语音播报
缺点
需要修改源码
升级镜像时需同步修改
但总体收益明显更高。
七、最终采用方案
1. 安装 ffmpeg
创建 Dockerfile:
FROM ghcr.io/coqui-ai/tts-cpu
RUN apt-get update && \
apt-get install -y ffmpeg && \
rm -rf /var/lib/apt/lists/*2. 构建镜像
docker build -t coqui-tts-custom .八、映射自定义 server.py
启动:
docker run -d \
--name coqui-tts \
--restart unless-stopped \
-p 5002:5002 \
-v /opt/tts-model:/root/.local/share/tts \
-v $(pwd)/server.py:/root/TTS/server/server.py \
--entrypoint python3 \
coqui-tts-custom \
TTS/server/server.py \
--model_name tts_models/zh-CN/baker/tacotron2-DDC-GST九、修改 server.py
默认:
synthesizer.save_wav(wavs, out)
return send_file(out, mimetype="audio/wav")修改为:
#导包
import subprocess
#代码调整
synthesizer.save_wav(wavs, out)
out.seek(0)
ffmpeg = subprocess.Popen(
[
"ffmpeg",
"-i", "pipe:0",
"-ar", "16000",
"-ac", "1",
"-c:a", "libmp3lame",
"-b:a", "24k",
"-f", "mp3",
"pipe:1"
],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL
)
mp3_data, _ = ffmpeg.communicate(input=out.read())
return send_file(
io.BytesIO(mp3_data),
mimetype="audio/mpeg"
)十、参数说明
十一、为什么推荐 16k+mono
语音场景:
不需要立体声
不需要44.1k高采样率因此:
即可满足:
机器人
TTS
语音播报
十二、MP3 与 OPUS 对比
MP3
优点:
兼容性极高
浏览器支持好
缺点:
压缩率一般
OPUS
优点:
专门为语音优化
超高压缩率
低延迟
缺点:
某些老设备兼容性一般
十三、最终推荐
Web/H5
推荐:
MP3
24kbpsMQTT/机器人/IoT
推荐:
OPUS
12kbps
mono
16kHz十四、最终效果
压缩前:
压缩后:
压缩率提升非常明显。
十五、生产建议
推荐:
Docker 持久化模型
server.py 挂载开发
ffmpeg 内置镜像
使用 mono + 16k
IoT 优先使用 OPUS、MP3
十六、总结
Coqui TTS 非常适合:
本地离线语音
局域网机器人
边缘 AI
MQTT 播报
IoT
通过扩展:
server.py + ffmpeg可以以极小改动实现:
MP3
OPUS
低码率
小体积
高兼容性
相比:
Nginx 转码
Java 中转
客户端压缩
直接扩展 server.py:
实现成本最低
性能最好
部署最简单尤其适合:
本地化机器人语音系统
评论区