ChatTTS 对话式 TTS 技术指南:安装部署、推理参数详解与两阶段自回归架构剖析
ChatTTS 是一款专为日常对话场景(如 LLM 助手语音输出)设计的生成式文本转语音(TTS)模型,支持中文与英语,并具备对笑声、停顿、插入语等韵律特征的精细控制能力。本文以中文官方文档 docs/cn/README.md 为主体,结合当前仓库源码,完整覆盖从环境安装、快速上手到 RefineTextParams/InferCodeParams 推理参数、说话人音色控制与零样本推理的实现原理,帮助读者既会用,也理解其底层调用链。
一、项目定位:为对话场景优化的生成式语音模型
ChatTTS 是面向对话式任务优化的 TTS 模型,官方仓库仅包含算法架构和一些简单的示例(示例代码位于 examples/ 目录)。由本仓库衍生出的用户端产品,可参见社区维护的 Awesome-ChatTTS 索引仓库;代码库的图解说明见 CodeBoarding 的 ChatTTS 可视化文档。
支持的语种
- 英语(已支持,文档标注"experimental"实验性)
- 中文(已支持)
- 其他语种:敬请期待
三大亮点
- 对话式 TTS:ChatTTS 针对对话式任务进行了优化,能够实现自然且富有表现力的合成语音,支持多个说话者,便于生成互动式对话。
- 精细的控制:模型可以预测和控制精细的韵律特征,包括笑声(laughter)、停顿(pauses)和插入语(interjections)。
- 更好的韵律:ChatTTS 在韵律方面超越了大多数开源 TTS 模型,官方提供预训练模型以支持进一步的研究和开发。
数据集与模型规模
- 主模型使用了 100,000+ 小时的中文和英文音频数据进行训练;
- HuggingFace 上开源的版本是一个在 40,000 小时数据上进行无监督微调(无 SFT)的预训练模型。
路线图(Roadmap)
| 状态 | 事项 |
|---|---|
| 已完成 | 开源 4 万小时基础模型和 spk_stats 文件 |
| 已完成 | 支持流式语音输出 |
| 已完成 | 开源 DVAE 编码器和零样本推理代码 |
| 待完成 | 开源具有多情感控制功能的 4 万小时版本 |
| 待完成 | ChatTTS.cpp(欢迎在 2noise 组织中新建仓库) |
许可证与免责声明
此仓库仅供学术用途,旨在用于教育和研究目的,不适用于任何商业或法律目的。数据来自公开来源,作者不声称对数据拥有任何所有权或版权。
值得注意的是其对抗滥用的设计:为了限制 ChatTTS 的滥用,官方在 40,000 小时模型的训练过程中添加了少量高频噪声,并使用 MP3 格式尽可能压缩音频质量,以防止恶意行为者将其用于犯罪目的。同时官方内部训练了一个检测模型,并计划在未来开源。合作洽谈可通过邮件 open-source@2noise.com 联系;线上讨论渠道包括 QQ 群(808364215 / 230696694 / 933639842 / 608667975)和 Discord。
二、环境准备与依赖安装
中文文档提示:此版本可能不是最新版,所有内容请以英文版 README.md 为准。
1. 克隆仓库
git clone https://github.com/2noise/ChatTTS
cd ChatTTS
2. 安装依赖
方式一:直接安装
pip install --upgrade -r requirements.txt
方式二:使用 conda 安装
conda create -n chattts
conda activate chattts
pip install -r requirements.txt
核心依赖清单可见 requirements.txt:torch>=2.1.0、transformers>=4.41.1、vocos(预训练声码器)、vector_quantize_pytorch(GVQ 向量量化)、pybase16384(说话人向量编码)、以及 Linux 平台下的文本正则化组件 pynini==2.1.5、WeTextProcessing、nemo_text_processing。
3. 可选加速组件(仅限 NVIDIA GPU / Linux)
TransformerEngine(安装过程可能耗时很长,适配仍在开发中,运行时可能遇到较多问题,仅推荐出于开发目的安装):
pip install git+https://github.com/NVIDIA/TransformerEngine.git@stable
对应实现位于 ChatTTS/model/cuda/ 目录(如 te_llama.py)。
FlashAttention-2(主要适用于 NVIDIA GPU,支持设备列表见 Hugging Face 文档):
pip install flash-attn --no-build-isolation
三、快速启动:WebUI 与命令行推理
确保在执行以下命令时,处于项目根目录下。
1. WebUI 可视化界面
python examples/web/webui.py
该入口基于 examples/web/webui.py,内部调用 gradio(已在 requirements.txt 中声明)。
2. 命令行交互
python examples/cmd/run.py "Your text 1." "Your text 2."
生成的音频将保存至 ./output_audio_n.mp3。深入 examples/cmd/run.py 源码可以看到它实际支持的完整参数(比文档一行命令更丰富):
| 参数 | 说明 |
|---|---|
--spk |
指定说话人向量(字符串形式),为空时调用 sample_random_speaker() 随机采样 |
--stream |
启用流式输出模式 |
--source |
模型来源:huggingface(从 HF 下载)/ local(ckpt 保存在 asset 目录)/ custom(自定义路径),默认 local |
--custom_path |
自定义模型路径(包含 asset ckpt 目录),配合 --source custom 使用 |
其核心调用链为:ChatTTS.Chat() 构建 → chat.load(source=source) 加载模型 → 无 --spk 时执行 chat.sample_random_speaker() → chat.infer(texts, stream, params_infer_code=InferCodeParams(spk_emb=spk)) → 将 PCM 数据经 pcm_arr_to_mp3_view 编码后写为 mp3。此外它还会尝试注册中英文文本正则化器(normalizer_en_nemo_text / normalizer_zh_tn,见 tools/normalizer/),缺失时提示安装 nemo_text_processing / WeTextProcessing。
四、开发教程:作为 Python 包安装
- 从 PyPI 安装稳定版:
pip install ChatTTS
- 从 GitHub 安装最新版:
pip install git+https://github.com/2noise/ChatTTS
- 从本地文件夹安装开发版:
pip install -e .
打包配置见 setup.py。
五、基础用法:四行代码完成合成
import ChatTTS
import torch
import torchaudio
chat = ChatTTS.Chat()
chat.load(compile=False) # Set to True for better performance
texts = ["PUT YOUR 1st TEXT HERE", "PUT YOUR 2nd TEXT HERE"]
wavs = chat.infer(texts)
torchaudio.save("output1.wav", torch.from_numpy(wavs[0]), 24000)
要点解析(对照 ChatTTS/core.py 中 load 方法签名):
compile=False:是否启用torch.compile。源码中compile and "cuda" in str(device)才真正触发编译(见 core.py),因此 CPU/MPS 下设置True无效;load还支持更多参数:source(huggingface/local/custom)、custom_path(自定义模型目录)、device(手动指定设备)、use_flash_attn、use_vllm、experimental、enable_cache(K/V 缓存);infer返回numpy波形数组列表,采样率为 24000 Hz,这一数值与 config.py 中 Vocos 特征提取器的sample_rate: int = 24000一致;- 若传入多条文本且开启
split_text(默认开启),最终返回的是按句号/换行切分后拼接合并的单一波形(见 core.py 中的分句与np.concatenate逻辑)。
六、进阶用法:说话人采样、句级与词级控制
完整进阶示例(与原文档一致,可直接运行):
###################################
# 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)
两类控制参数的完整默认值
这两个 dataclass 定义在 ChatTTS/core.py,InferCodeParams 继承自 RefineTextParams 并覆盖了部分默认值:
| 参数 | RefineTextParams 默认 | InferCodeParams 默认 | 作用 |
|---|---|---|---|
prompt |
"" |
"[speed_5]" |
控制前缀。refine 阶段用 [oral_*]/[laugh_*]/[break_*] 控制句级韵律;code 阶段用 [speed_*] 等控制语速 |
spk_emb |
— | None |
说话人向量字符串(sample_random_speaker() 的返回值),实现音色控制 |
spk_smp / txt_smp |
— | None |
零样本音色参考:spk_smp 为参考音频的语义 token 提示,txt_smp 为参考文本 |
top_P / top_K |
0.7 / 20 | 继承 | 采样核参数 |
temperature |
0.7 | 0.3 | 解码温度,code 阶段默认更保守 |
repetition_penalty |
1.0 | 1.05 | 重复惩罚 |
max_new_token |
384 | 2048 | 最大新生成 token 数 |
min_new_token |
0 | 0 | 最小生成 token 数 |
stream_batch |
— | 24 | 流式生成的批 token 数 |
stream_speed |
— | 12000 | 每块输出的采样点数(约 0.5s 音频) |
pass_first_n_batches |
— | 2 | 流式时跳过的首批数量(降低首包延迟策略) |
manual_seed |
None |
None |
手动种子,保证可复现 |
句级控制与词级控制的区别
- 句级控制:通过
RefineTextParams.prompt传入[oral_0~9]、[laugh_0~2]、[break_0~7]等控制标记,让文本精炼阶段(refine)在待合成文本中自动插入特殊 token,从而控制口头语、笑声和停顿的倾向; - 词级控制:直接在文本中手写
[uv_break](短语间停顿)、[laugh](触发笑声)、[lbreak](笑声后停顿)等 token 级控制单元,并以skip_refine_text=True跳过精炼阶段,完全由用户决定韵律位置。从源码结构看,skip_refine_text=True时_infer直接使用原始文本编码,不再经过_refine_text(见 core.py)。
七、底层架构:两阶段推理流水线与核心组件
从 ChatTTS/core.py 的 Chat._infer(L390-L508)可以看出,一次完整推理由三个阶段构成:
输入文本
│ ① 文本正则化(Normalizer,可选同音字替换)
▼
_refine_text —— GPT 第一阶段:文本精炼,插入 [uv_break]/[laugh]/[lbreak] 等韵律 token
▼
_infer_code —— GPT 第二阶段:自回归生成多层 VQ 语义 token(num_vq=4)
▼
_decode_to_wavs—— DVAE decoder 将语义 token 解为 Mel 谱 → Vocos 声码器还原波形
GPT 主干与 VQ 语义 token
ChatTTS/config/config.py 定义了主干规模:hidden_size=768、num_hidden_layers=20、num_attention_heads=12、max_position_embeddings=4096,以及 num_audio_tokens=626、num_text_tokens=21178、num_vq=4、spk_emb_dim=192。
626 这个数字恰好对应 DVAE 的 GVQ 向量量化配置(config.py 中 levels=(5,5,5,5),即 5^4 = 625 个量化码 + 1 个结束符)。这与 README"致谢"中提到的思路一致:fish-speech 揭示了 GVQ 作为 LLM 建模音频分词器的能力。
采样侧逻辑在 ChatTTS/model/processors.py 的 gen_logits 中:组装 TopPLogitsWarper、TopKLogitsWarper(均设 min_tokens_to_keep=3)以及自定义的 CustomRepetitionPenaltyLogitsProcessorRepeat(重复惩罚仅统计最近 16 个 token 窗口),对应上面 InferCodeParams 中 top_P/top_K/repetition_penalty 参数的落地位置。
说话人向量的采样、编码与零样本推理
Speaker 模块位于 ChatTTS/model/speaker.py:
- 随机采样:
sample_random_speaker()(对应sample_random,L18-L19)按高斯分布采样——randn(192) * std + mean(_sample_random),其中均值/标准差来自官方开源的 spk_stats 文件(以 base16384 + lzma 压缩的字符串形式内嵌在 config.py 的spk_stat字段中)。采样结果序列化为可打印字符串,保存该字符串即可在后续恢复同一音色; - 音色注入:推理时
decorate_code_prompts(L56-L82)把文本包装为[Stts][spk_emb]{txt_smp}{text}[Ptts]模板,Speaker.apply(L22-L52)再将归一化后的 192 维说话人向量替换到[spk_emb]位置对应的 embedding 上; - 零样本音色推理:
sample_audio_speaker(wav)(见 core.py)先用 DVAE 编码器(dvae.sample_audio)提取参考音频的语义 prompt,再speaker.encode_prompt压缩成spk_smp字符串。此外源码还有一个隐式行为值得注意:当输入多句文本且未显式提供spk_smp时,_infer会先用第一句合成音频并提取spk_smp/txt_smp(core.py),使后续句子自动保持音色一致。
设备与回退策略
_load(core.py)按顺序加载 Vocos → DVAE → Embed → GPT → Speaker → Decoder → Tokenizer 七个组件,并对异构设备做了处理:MPS 下 GPT 回退 CPU(device_gpt)、Vocos 在 MPS/NPU 下回退 CPU;支持 use_vllm(实验性 vLLM 引擎,见 ChatTTS/model/velocity/)路径。coef 参数则用于加载 DVAE/Decoder 时替换量化因子。
八、完整示例:英文自我介绍
inputs_en = """
chatTTS 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 like
[uv_break]laughter[uv_break][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)
该示例展示了词级 [uv_break]/[laugh] 与句级 prompt 标记的组合使用,原文档附带了男性/女性两种音色合成效果对比。
九、常见问题(FAQ)
1. 需要多少 VRAM?推理速度如何?
官方文档给出的数据:对于 30 秒的音频片段,至少需要 4GB 的 GPU 内存;在 4090 GPU 上,每秒可生成大约 7 个语义 token 对应的音频,实时因子(RTF)约为 0.3。
2. 模型稳定性不够好,存在多个说话者混入或音频质量差的问题?
这是通常发生在自回归模型(例如 bark 和 valle)中的一类问题,通常很难避免。官方建议尝试多个样本以找到合适的结果。结合上文源码分析,可复现性地定位好样本可配合 RefineTextParams.manual_seed 使用。
3. 除了笑声,还能控制其他东西吗?能控制其他情绪吗?
在当前发布的模型中,可用的 token 级控制单元是 [laugh]、[uv_break] 和 [lbreak] 三个。结合路线图可知,具有多情感控制功能的 4 万小时版本尚未开源,未来版本可能会开放更多情绪控制能力。
十、致谢与技术渊源
- bark、XTTSv2 和 valle 通过自回归式系统展示了出色的 TTS 效果;
- fish-speech 揭示了 GVQ 作为 LLM 建模的音频分词器的能力(正是本文第七节中 4 层 VQ 语义 token 方案的来源);
- vocos 被用作预训练声码器(
_load中的第一步加载对象即Vocos); - 特别鸣谢 wlu-audio lab 对早期算法实验的支持。
综合来看,ChatTTS 的完整链路为:文本正则化 → GPT 文本精炼(插入韵律 token)→ GPT 自回归生成 4 层 GVQ 语义 token → DVAE 解码为 Mel 谱 → Vocos 声码还原 24kHz 波形;开发者通过 RefineTextParams.prompt、InferCodeParams(spk_emb/采样核/流式参数)与文本内嵌 token 三个层次对其进行控制。以上所有行为均可在 ChatTTS/core.py、ChatTTS/config/config.py、ChatTTS/model/speaker.py 与 examples/ 示例中逐一验证。
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