Coqui-TTS Mary-TTS 兼容 API:用 /locales、/voices 与 /process 三个端点替换经典 TTS 服务
【免费下载链接】TTS🐸💬 - a deep learning toolkit for Text-to-Speech, battle-tested in research and production项目地址: https://gitcode.com/GitHub_Trending/tt/TTS
本篇围绕 Coqui-TTS 仓库中的 Mary-TTS 兼容层文档 marytts.md 展开:它说明 Coqui-TTS 的 Flask 演示服务器如何通过三个 Mary-TTS 风格 HTTP 端点(/locales、/voices、/process)兼容旧有 Mary-TTS 客户端,并逐一拆解 server.py 中各端点的源码实现、参数解析细节与已知限制,帮助读者把 Coqui-TTS 作为传统 Mary-TTS 服务的“即插即用”替换项接入屏幕阅读器、智能家居或语音助手类工具链。
一、Mary-TTS 是什么,为什么值得做兼容
Mary(Modular Architecture for Research in sYnthesis)Text-to-Speech 是一个用 Java 编写的开源(GNU LGPL)多语言 TTS 平台,最初由德国 DFKI 语言技术实验室与萨尔兰大学语音学研究所合作开发,后由 MMCI 卓越集群与 DFKI 的语音处理小组维护。该项目的历史相当悠久:3.0 版本可追溯到 2006 年(远早于深度学习成为通用术语的时代),最后一个官方版本 5.2 发布于 2016 年。
正是由于开源、音质尚可、合成速度快,Mary-TTS 在过去十年被大量工具集成,形成了稳定的 HTTP API 调用习惯。原文档列举的典型集成方包括:
- 屏幕阅读器:NVDA + SpeechHub;
- 智能家居中心:openHAB、Home Assistant;
- 语音助手:Rhasspy、Mycroft、SEPIA。
这些工具多年只对接 Mary-TTS 的 HTTP 接口。Coqui-TTS 提供兼容层后,上述工具无需修改代码,即可把服务端指向 Coqui-TTS,直接获得更高质量的深度学习语音——这是本文讨论的兼容性层存在的根本意义。
二、Mary-TTS HTTP API 的三个最小可用端点
Mary-TTS 本身提供大量端点(加载 style、音频效果、示例等),但据原文档总结,大多数兼容工具只需要其中 3 个即可正常工作。Coqui-TTS 的兼容层正是按这个“最小集合”实现的:
1./locales(GET)——返回受支持的语言环境
返回格式为每行一个 locale 的纯文本,例如en_US、de_DE或简写的en,行以\n分隔。
2./voices(GET)——返回可用语音列表
返回格式为每行名称 语言环境 性别,例如glow-tts en u。其中:
- 名称不能包含空格(Mary-TTS 约定);
- 性别字段传统上取
f(女)或m(男)。
3./process(GET/POST)——核心合成端点
完整示例 URL(经典 Mary-TTS 参数风格):
/process?INPUT_TEXT=[my text]&INPUT_TYPE=TEXT&LOCALE=[locale]&VOICE=[name]&OUTPUT_TYPE=AUDIO&AUDIO=WAVE_FILE服务端处理输入文本并返回一个 WAV 文件。INPUT_TYPE、OUTPUT_TYPE、AUDIO等参数虽然支持其他取值,但在兼容工具中通常是固定值。
三、启动服务器并用 curl 验证兼容端点
兼容层构建在 Coqui-TTS 自带的 Flask 演示服务器之上。服务器入口为 TTS/server/server.py,pip 安装后还可以直接使用tts-server命令(见 setup.py 中的entry_points定义:tts-server = TTS.server.server:main)。
要获得“经典 Mary-TTS 兼容”体验,关键点在于端口:文档建议监听59125(这是 Mary-TTS 客户端的默认端口习惯值,而非 Coqui-TTS 演示服务器默认的5002)。以官方预训练模型为例:
python TTS/server/server.py \ --model_name tts_models/en/ljspeech/tacotron2-DDC \ --port 59125--model_name的取值格式为<language>/<dataset>/<model_name>(在 server.py 的 argparse 定义中可见,默认值即tts_models/en/ljspeech/tacotron2-DDC)。也可以用自定义 checkpoint 启动,各参数的说明可参考 TTS/server/README.md。
服务器启动后,按文档给出的三条 curl 命令逐一验证:
返回当前活跃语音的 locale,例如en:
curl http://localhost:59125/locales返回当前活跃语音的名称,例如glow-tts en u:
curl http://localhost:59125/voices对输入文本进行合成,保存为 wav 文件:
curl "http://localhost:59125/process?INPUT_TEXT=this+is+a+test" > test.wav注意原文档中第三条命令未加引号(curl http://localhost:59125/process?INPUT_TEXT=this+is+a+test > test.wav),在多数 shell 中?与+无需转义可以原样执行;但一旦文本中包含空格之外的特殊字符,建议用引号包裹 URL。也可以把这些 URL 直接粘贴到浏览器中查看结果。
四、源码解析:三个端点如何把“单模型服务器”伪装成“Mary-TTS 服务器”
兼容层的全部实现集中在 TTS/server/server.py 的# Basic MaryTTS compatibility layer区块。以下逐一对照源码说明其设计。
/locales:从 model_name 拆出语言段
@app.route("/locales", methods=["GET"]) def mary_tts_api_locales(): """MaryTTS-compatible /locales endpoint""" # NOTE: We currently assume there is only one model active at the same time if args.model_name is not None: model_details = args.model_name.split("/") else: model_details = ["", "en", "", "default"] return render_template_string("{{ locale }}\n", locale=model_details[1])实现方式是把--model_name按/切分:tts_models/en/ljspeech/tacotron2-DDC切分后下标 1 恰为语言码en,于是返回en\n。若未指定model_name,则回退为["", "en", "", "default"],同样返回en。源码注释明确承认前提:同一时间只有一个模型处于活跃状态,因此无法像真正的 Mary-TTS 服务器那样枚举全部已安装 locale。
/voices:模型名充当“voice”,性别固定为u
return render_template_string( "{{ name }} {{ locale }} {{ gender }}\n", name=model_details[3], locale=model_details[1], gender="u" )- voice 名称取自 model_name 的最后一段(下标 3),如
tacotron2-DDC——注意 Mary-TTS 要求名称不含空格,官方模型名天然满足; - locale与
/locales相同,取切分后的第 2 段; - 性别固定返回
u(undefined),因为 Coqui-TTS 的模型体系没有“男声/女声”这一元数据概念。
对tts_models/en/ljspeech/tacotron2-DDC,该端点实际输出tacotron2-DDC en u\n。
/process:只取INPUT_TEXT,其余参数全部忽略
@app.route("/process", methods=["GET", "POST"]) def mary_tts_api_process(): """MaryTTS-compatible /process endpoint""" with lock: if request.method == "POST": data = parse_qs(request.get_data(as_text=True)) # NOTE: we ignore param. LOCALE and VOICE for now since we have only one active model text = data.get("INPUT_TEXT", [""])[0] else: text = request.args.get("INPUT_TEXT", "") print(f" > Model input: {text}") wavs = synthesizer.tts(text) out = io.BytesIO() synthesizer.save_wav(wavs, out) return send_file(out, mimetype="audio/wav")几个值得注意的实现细节:
- GET 与 POST 双支持:GET 请求从 URL 查询串取
INPUT_TEXT;POST 请求用urllib.parse.parse_qs解析请求体文本后取INPUT_TEXT。这覆盖了不同工具对 Mary-TTS 的两种调用习惯。 - 只读
INPUT_TEXT:LOCALE、VOICE、INPUT_TYPE、OUTPUT_TYPE、AUDIO等参数全部忽略——因为服务器只有一个活跃模型,且永远返回 WAV,其余参数没有实际作用。源码注释直接写明了忽略LOCALE/VOICE的原因。 with lock:串行化:模块级lock = Lock()(定义于 server.py)保证同一时刻只有一路合成在跑,避免多线程并发推理产生竞争。这对单模型演示服务器是合理的取舍,但也意味着 Mary-TTS 兼容端点不是并发服务,高吞吐场景需要自行扩展。- 输出格式:
synthesizer.tts(text)得到波形列表后写入内存BytesIO,以mimetype="audio/wav"通过 Flasksend_file流式返回,正好匹配 Mary-TTS 客户端对AUDIO=WAVE_FILE的预期。
合成链路:Synthesizer.tts内部做了什么
synthesizer.tts(text)实现在 TTS/utils/synthesizer.py。Mary-TTS 端点传入的只有text,因此实际执行路径是:
- 用
pysbd.Segmenter(language="en")把输入文本按英文断句切分为句子列表(split_sentences=True为默认); - 逐句调用 TTS 模型的
synthesize或通用synthesis函数生成波形; - 若配置了独立声码器,将 mel 频谱反归一化(TTS 音频配置)、再按声码器配置归一化、必要时对采样率不匹配做插值,最后走声码器
inference还原波形;未配置声码器时回退 Griffin-Lim; - 各句波形拼接(句间插入 10000 个采样点的静音)返回。
由此可得两个与兼容层相关的实践结论:
- 文本按英文断句:
Segmenter在服务器初始化时硬编码为en(见 synthesizer.py 的self._get_segmenter("en"))。也就是说/process端点的断句行为面向英文文本,用其他语言的model_name(如de、fr)启动时,端点本身仍可返回正确 locale,但断句器仍按英文规则切分——这是源码结构可见的局限。 - Mary-TTS 端点不传 speaker/language 参数:与同一服务器里的
/api/tts端点(支持speaker-id、language-id、style-wav,见 server.py)不同,/process只调用synthesizer.tts(text)。因此若加载的是多说话人/多语言模型,经 Mary 兼容端点合成时不会指定说话人与语言,可能触发Synthesizer内部的参数校验异常(例如要求提供speaker_idx的报错,见 synthesizer.py)。对单说话人模型(如 LJSpeech 系列)则无此问题。
五、与经典 Mary-TTS 服务器的行为差异及取舍
原文档“How it works and limitations”一节可以归纳为下表:
| 维度 | 经典 Mary-TTS 服务器 | Coqui-TTS 兼容端点 |
|---|---|---|
/locales | 列出全部已安装 locale | 只返回当前活跃模型的单一 locale |
/voices | 列出全部已安装语音 | 只返回当前模型名作为唯一 voice |
/process参数 | 接受LOCALE、VOICE等并据此选择资源 | 仅使用INPUT_TEXT,其余参数忽略 |
| 性别字段 | 传统f/m | 固定u(Coqui-TTS 模型无性别定义) |
| 输出格式 | 按OUTPUT_TYPE/AUDIO参数 | 恒定 WAV |
作者的结论是:这属于可接受的折中——大多数用户本来就只关心某一个特定语音,兼容层足以让存量工具直接切换过来;API 未来可能扩展为同时支持多语言、多语音。这一判断也与源码中两处NOTE: We currently assume there is only one model active at the same time注释完全一致。
六、验证与延伸阅读
- 兼容端点源码:TTS/server/server.py;
- 演示服务器启动方式与参数:TTS/server/README.md;
- 推理主链路(断句、合成、声码器、实时率统计):TTS/utils/synthesizer.py;
- 主题原始文档:docs/source/marytts.md。
需要说明的适用前提:Mary-TTS 端点与/api/tts一样运行在演示服务器上,受全局锁串行化约束,定位为“兼容替换”而非高并发生产网关;/locales与/voices的信息仅反映启动时通过--model_name指定的那一个模型,切换语音需要更换模型并重启服务器。理解了这些边界之后,读者即可把 NVDA、openHAB 或 Rhasspy 一类工具的 Mary-TTS 服务端地址直接指向http://<host>:59125,用文中三条 curl 命令完成自检。
【免费下载链接】TTS🐸💬 - a deep learning toolkit for Text-to-Speech, battle-tested in research and production项目地址: https://gitcode.com/GitHub_Trending/tt/TTS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考