ChatTTS 西班牙语官方文档精讲:面向日常对话的 TTS 模型安装、推理与韵律控制实战
本文以 ChatTTS 仓库的西班牙语官方文档 docs/es/README.md 为主体,结合仓库中 ChatTTS/core.py、examples/cmd/run.py 等源码,完整讲解这个面向 LLM 对话场景的语音生成模型的定位、安装流程、WebUI/命令行/Python API 三种使用方式,以及 spk_emb、temperature、[oral_*]、[laugh_*]、[break_*] 等参数和韵律控制标记的底层实现,读完后可独立完成部署、推理与细粒度语音控制。
一、项目定位:为对话场景优化的 TTS
ChatTTS 是一个专为 LLM assistant 等对话场景设计的文本转语音(text-to-speech)模型。西班牙语文档对其三大特性的概括如下:
- TTS Conversacional(对话式 TTS):针对对话任务优化,能够合成自然、富表现力的语音,并支持多说话人(multi-speaker),便于生成交互式对话。
- Control Fina(细粒度控制):模型可以预测并控制韵律上的细节特征,包括笑声(risas)、停顿(pausas)和语气词(interjecciones)。
- Mejor Prosodia(更优韵律):在韵律表现上超过多数开源 TTS 模型;项目提供预训练模型以支持后续研究与开发。
支持语言方面,官方清单为:
- [x] 英语(English)
- [x] 中文(Chino)
- [ ] 其他语言持续跟进中
数据集与模型规模(文档原样声明,仅用于学术用途):
- 主模型使用超过 100,000 小时中英文音频数据训练;
- 开源版本(托管于 HuggingFace 的
2Noise/ChatTTS)是 40,000 小时预训练模型,未经 SFT 微调。
**路线图(Hoja de Ruta)**中已完成项为公开 40k 小时基础模型与 spk_stats 文件,未完成项包括开源 VQ 编码器与 LoRA 训练代码、不经过文本精化的流式音频生成、多情绪控制版本以及 ChatTTS.cpp(社区 PR 欢迎)。
免责声明(Descargo de Responsabilidad)值得特别注意:文档明确说明仓库仅用于学术目的,并解释了两项限制措施——在 40,000 小时模型的训练过程中加入了少量高频噪声,并将音频以 MP3 格式尽可能压缩音质,以防止恶意用途;同时官方表示内部已训练一个检测模型并计划未来开源。代码协议为 AGPLv3+,模型权重为 CC BY-NC 4.0(不可商用)。
二、安装与环境准备
西班牙语文档给出的安装方式为从源码安装(文档标注该包“即将上架 PyPI”):
pip install git+https://github.com/2noise/ChatTTS
从仓库当前 requirements.txt 可以看到核心依赖约束:torch>=2.1.0、torchaudio、transformers>=4.41.1、vocos、vector_quantize_pytorch、numba、gradio、pybase16384、av、pydub 等;其中 pynini==2.1.5、WeTextProcessing、nemo_text_processing 这三个文本归一化依赖仅限 Linux 平台安装。这对应了 examples/cmd/run.py 中 load_normalizer() 的行为——命令行示例会尝试注册英文(NeMo)与中文(WeTextProcessing)归一化器,失败时降级为警告而不中断。
两种推荐安装方式:
方式 1:直接安装
pip install --upgrade -r requirements.txt
方式 2:使用 conda 独立环境
conda create -n chattts
conda activate chattts
pip install -r requirements.txt
从源码结构看,chat.load() 还支持 source(huggingface / local / custom)、device、use_flash_attn、use_vllm、experimental、enable_cache 等更多参数,模型校验依赖 ChatTTS/res/sha256_map.json 逐文件比对哈希,详见 ChatTTS/core.py。
三、快速上手:WebUI 与命令行推理
文档的 Inicio Rápido(快速开始)给出两条路径,执行前请确保处于项目根目录:
1. 启动 WebUI
python examples/web/webui.py
对应实现位于 examples/web/webui.py 与 examples/web/funcs.py。从 funcs.py 的源码可以看到,WebUI 预置了 “Timbre1~Timbre9” 共 9 种音色,其本质是固定随机种子(1111、2222、…、9999)下调用 sample_random_speaker() 得到的说话人嵌入——也就是说,预置音色与 API 的随机音色出自同一套高斯采样机制。
2. 命令行推理
python examples/cmd/run.py "Please input your text."
文档说明音频将保存到 ./output_audio_xxx.wav;按当前仓库 run.py 的实现,实际产物为 output_audio_{index}.mp3(通过 tools.audio.pcm_arr_to_mp3_view 编码)。该脚本的完整参数为:
[--spk xxx] [--stream] [--source ***] [--custom_path XXX] "Your text 1." "Your text 2."
--spk:指定音色(传入sample_random_speaker()生成的字符串);缺省时随机采样;--stream:启用流式模式;--source:模型来源,huggingface/local/custom三选一;--custom_path:自定义模型目录;- 其余位置参数为待合成文本,可一次传多条。
--stream 模式下的完整流式播放链路可参考 examples/cmd/stream.py,其中 ChatStreamer 类按 24000 Hz、16 位单声道 PCM 组织字节流并优先缓冲一段再播放,适合 CPU 等生成较慢的环境。
四、Python API:基础用法
文档 Básico 一节的最小可用示例(代码原样继承,输出采样率 24000 Hz):
import ChatTTS
from IPython.display import Audio
import torchaudio
import torch
chat = ChatTTS.Chat()
chat.load(compile=False) # Set to True for better performance
texts = ["PUT YOUR TEXT HERE",]
wavs = chat.infer(texts)
torchaudio.save("output1.wav", torch.from_numpy(wavs[0]), 24000)
结合 ChatTTS/core.py 的 infer() 实现,可以明确几个行为细节:
infer()默认split_text=True:若输入是单个字符串,会先按换行符或。/.断句切分,再逐段推理,最后把各段音频拼接并裁掉首尾静音(阈值1e-5)返回;- 每个合成句会经历两阶段流水线:
_refine_text(文本精化,可插入韵律标记)→_infer_code(自回归生成语义/声学 token),再经 DVAE 解码 + Vocos 声码器还原波形(见_decode_to_wavs); - 多句输入且未指定
spk_smp时,源码会先推理第一句,再用sample_audio_speaker()从该句音频反推说话人提示,从而保证整批文本音色一致(core.py L440-L458)。
五、进阶用法:说话人控制与韵律标记
文档 Avanzado 一节完整给出三级控制示例,这里原样保留并结合源码逐段解析:
###################################
# Sample a speaker from Gaussian.
rand_spk = chat.sample_random_speaker()
print(rand_spk) # save it for later timbre recovery
params_infer_code = ChatTTS.Chat.InferCodeParams(
spk_emb = rand_spk, # add sampled speaker
temperature = .3, # using custom temperature
top_P = 0.7, # top P decode
top_K = 20, # top K decode
)
###################################
# For sentence level manual control.
# use oral_(0-9), laugh_(0-2), break_(0-7)
# to generate special token in text to synthesize.
params_refine_text = ChatTTS.Chat.RefineTextParams(
prompt='[oral_2][laugh_0][break_6]',
)
wavs = chat.infer(
texts,
params_refine_text=params_refine_text,
params_infer_code=params_infer_code,
)
###################################
# For word level manual control.
text = 'What is [uv_break]your favorite english food?[laugh][lbreak]'
wavs = chat.infer(text, skip_refine_text=True, params_refine_text=params_refine_text, params_infer_code=params_infer_code)
torchaudio.save("output2.wav", torch.from_numpy(wavs[0]), 24000)
5.1 说话人嵌入(spk_emb)的生成与复用
chat.sample_random_speaker() 的实现在 ChatTTS/model/speaker.py:以随模型发布的 spk_stats(均值与标准差,base64 解码后为 float16 张量)为参数做高斯采样 randn * std + mean,再把结果 float16 序列化 + LZMA 压缩 + base64 编码成一个字符串。打印并保存这个字符串即可在之后的会话中原样恢复同一音色(timbre recovery)。推理时,Speaker.apply() 会把该嵌入按 L2 归一化后,写入输入序列中 [spk_emb] 占位符对应位置的嵌入向量;decorate_code_prompts() 则把每条文本包装成 [Stts][spk_emb]{文本}[Ptts] 的提示模板。
5.2 两个参数数据类的完整字段与默认值
文档示例只展示了部分字段。以 ChatTTS/core.py L184-L208 的 @dataclass 定义为准,完整参数如下表(这是比文档更可直接落地的取值参考):
RefineTextParams(文本精化阶段,作用于 refine 子模型)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
prompt |
str | "" |
句级控制提示,如 '[oral_2][laugh_0][break_6]' |
top_P |
float | 0.7 |
核采样(nucleus)阈值 |
top_K |
int | 20 |
top-K 解码 |
temperature |
float | 0.7 |
采样温度 |
repetition_penalty |
float | 1.0 |
重复惩罚 |
max_new_token |
int | 384 |
最大新生成 token 数 |
min_new_token |
int | 0 |
最少生成 token 数 |
show_tqdm |
bool | True |
是否显示进度条 |
ensure_non_empty |
bool | True |
强制非空输出 |
manual_seed |
Optional[int] | None |
手动随机种子 |
InferCodeParams(代码生成阶段,继承自 RefineTextParams,覆盖默认值)
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
prompt |
str | "[speed_5]" |
默认速度档位提示 |
spk_emb |
Optional[str] | None |
高斯采样得到的说话人字符串 |
spk_smp |
Optional[str] | None |
从参考音频反推的说话人提示(多句自动对齐用) |
txt_smp |
Optional[str] | None |
参考文本 |
temperature |
float | 0.3 |
注意默认比 refine 阶段更低 |
repetition_penalty |
float | 1.05 |
重复惩罚 |
max_new_token |
int | 2048 |
最大生成长度 |
stream_batch |
int | 24 |
流式生成的 batch token 数 |
stream_speed |
int | 12000 |
每批流式输出的采样数(24 kHz 下约 0.5 秒) |
pass_first_n_batches |
int | 2 |
流式时跳过的首批批次数 |
stream_speed=12000 与 pass_first_n_batches 这两个字段的消费逻辑见 _infer 中流式分支:每生成一批先解码整段,再按 length ~ length + stream_speed 切片 yield,首批前 2 批直接丢弃以降低首包延迟感。
5.3 句级控制 vs 词级控制
- 句级(RefineTextParams.prompt):
oral_(0-9)控制口语化程度、laugh_(0-2)控制笑声倾向、break_(0-7)控制停顿倾向。这些标记写在 prompt 里,由 refine 子模型在文本精化阶段“自动”把相应标记插入到文本的合理位置——适合不想逐词手动标注的场景。 - 词级(skip_refine_text=True):直接在原文中手写
[uv_break](停顿)、[laugh](笑)、[lbreak](短句断点),并传skip_refine_text=True跳过精化阶段,标记位置完全由用户掌控,确定性最高。
六、官方示例:模型自我介绍
文档附带一个可直接运行的英文示例(文档注明“English is still experimental”):
inputs_en = """
chat T T S is a text to speech model designed for dialogue applications.
[uv_break]it supports mixed language input [uv_break]and offers multi speaker
capabilities with precise control over prosodic elements [laugh]like like
[uv_break]laughter[laugh], [uv_break]pauses, [uv_break]and intonation.
[uv_break]it delivers natural and expressive speech,[uv_break]so please
[uv_break] use the project responsibly at your own risk.[uv_break]
""".replace('\n', '') # English is still experimental.
params_refine_text = ChatTTS.Chat.RefineTextParams(
prompt='[oral_2][laugh_0][break_4]',
)
audio_array_en = chat.infer(inputs_en, params_refine_text=params_refine_text)
torchaudio.save("output3.wav", torch.from_numpy(audio_array_en[0]), 24000)
文档同时提供了男声、女声两个效果对比音频(见 docs/es/README.md 原文中的 male/female speaker 表格),展示了同一文本在不同 spk_emb 下的音色差异。
七、常见问题(FAQ)解析
文档 Preguntas y Respuestas 给出三条高频问题与官方答复:
1. 需要多少显存?推理速度如何?
对一段 30 秒音频,至少需要 4 GB GPU 显存。以 RTX 4090 为例,可生成约每秒 7 个语义 token 的音频,实时率(RTF)约 0.3,即生成速度约为实时的 3 倍。
2. 模型稳定性不够好,出现多说话人串音或音质差怎么办?
官方承认这是自回归模型(如 bark、valle)的共性难题,通常难以完全避免,建议多次采样挑选满意的结果。这与 InferCodeParams 中 temperature/top_P/top_K 可调、以及 RefineTextParams.manual_seed 支持固定种子复现的设计相互印证。
3. 除了笑声还能控制什么?能否控制其他情绪?
当前发布版本中,token 级控制单元仅有 [laugh]、[uv_break]、lbreak 三类;官方表示未来可能开源具备更多情绪控制能力的模型。这也解释了 RefineTextParams.prompt 中可用的 oral_/laugh_/break_ 档位组合,以及路线图里 “Multi-emotion controlling” 仍未勾选的原因。
八、可进一步深入的仓库文件索引
围绕本文内容,以下仓库路径适合继续深挖:
- ChatTTS/core.py:
Chat主类、load/infer/_refine_text/_infer_code完整推理链路; - ChatTTS/model/speaker.py:说话人高斯采样、编码解码与提示模板拼装;
- ChatTTS/model/tokenizer.py:基于 BertTokenizerFast 的编码、
[spk_emb]/[break_0]/[Ebreak]特殊 token 定义; - ChatTTS/res/homophones_map.json 与 ChatTTS/norm.py:推理前的同音字替换与文本归一化;
- examples/api/:基于 FastAPI 的 API 服务与 OpenAI 兼容接口示例;
- tests/testall.sh 及 tests/ 目录:按 GitHub issue 编号组织的回归测试脚本,可用
sh tests/testall.sh逐一运行验证。
最后重申文档的合规边界:模型权重为 CC BY-NC 4.0,仅限学术与科研用途,不得用于商业或非法目的;官方已通过训练期高频噪声注入与 MP3 音质压缩来限制其被滥用于伪造语音的风险。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00