ComfyUI 与 ChatTTS 实战:从零构建语音合成工作流
·
背景与痛点
语音合成(TTS)早已不是“朗读文本”这么简单:短视频自动配音、客服机器人、有声书批量生产,甚至游戏 NPC 的实时对话,都在把“秒级、低成本、高自然度”的语音当成刚需。
可真正动手时,新手往往卡在三点:
- 环境拼积木:Python 版本、PyTorch CUDA 驱动、音频依赖库,一步错步步错。
- 流程黑盒子:模型权重、Vocoder、声码器、采样率,参数散落在不同仓库,缺乏可视化调试。
- 生产难落地:并发请求一上来,GPU 显存爆炸;长文本分段不当,停顿诡异;偶尔网络抖动,整条工作流直接崩。
ComfyUI 把 Stable Diffusion 的“节点式”玩法带到语音领域,再接入专为对话场景微调的 ChatTTS,正好把“环境+流程+生产”串成一条可拖拽的透明管线,让入门门槛瞬间降到“会点 Python 就能玩”。
技术选型:为什么选 ChatTTS
| 维度 | ChatTTS | 常见云端 API | 本地 FastSpeech2 |
|---|---|---|---|
| 自然度 | 4.2/5(MOS) | 4.4/5 | 3.8/5 |
| 中文韵律 | 专为对话优化,停顿自然 | 通用模型,偶尔机器腔 | 需额外训练 |
| 离线可商用 | 权重可下载,Apache 2.0 | 按量计费+合规审核 | 可离线,但需自己找声码器 |
| 硬件成本 | 6G 显存可跑 | 零硬件,按调用付费 | 4G 显存,但音质差一截 |
结论:想要“免费+离线+中文聊天感”,ChatTTS 是当前本地方案里最省心的那一个。
核心实现
1. ComfyUI 环境配置详解
官方仓库已提供一键整合包,但自己动手三步更清爽:
- 新建 Python 3.10 虚拟环境,CUDA 11.8 驱动≥522.06。
- 安装 ComfyUI 主程序:
git clone https://github.com/comfyanonymous/ComfyUI.git cd ComfyUI pip install -r requirements.txt - 把 ChatTTS 作为“自定义节点”放进去:
权重会在首次运行时自动下载到cd custom_nodes git clone https://github.com/2Noise/ComfyUI-ChatTTS cd ComfyUI-ChatTTS pip install -r requirements.txtmodels/ChatTTS/。
2. ChatTTS API 集成步骤
节点内部其实只干两件事:
- 加载
ChatTTS.ChatTTS()模型实例,常驻显存。 - 把前端输入的“文本 + 音色种子”打包成
params_infer_code,调用model.infer()拿到 16kHz 波形,再转回 ComfyUI 的AUDIO类型。
核心代码片段(已含异常捕获):
import ChatTTS
import torch
import numpy as np
class ChatTTSNode:
def __init__(self):
self.model = None
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
def load_model(self):
if self.model is None:
self.model = ChatTTS.ChatTTS()
self.model.load(compile=False) # 编译可提速,但首次慢
return self.model
def generate(self, text, seed=42, speed=1.0, temperature=.3):
model = self.load_model()
torch.manual_seed(seed)
wavs = model.infer(
[text],
params_infer_code={
'spk_emb': None, # 随机音色
'temperature': temperature,
'top_P': 0.7,
'top_K': 20,
'prompt': "[speed_{}]".format(speed)
}
)
# wavs[0] 是 16kHz 浮点数组,直接返回
return (wavs[0] * 32767).astype(np.int16)
3. 工作流节点设计
拖拽界面里只需四个节点即可跑通:
TextInput→ 输入待合成文本ChatTTSNode→ 上方代码封装SaveAudio→ 输出 wav 到本地PreviewAudio→ 前端直接播放

节点之间用 AUDIO 类型连线,采样率统一 16kHz,避免二次重采样失真。
完整代码示例:文本预处理 → 语音输出
以下脚本脱离 ComfyUI 也能跑,方便单元测试:
# tts_cli.py
import ChatTTS
import torch
import soundfile as sf
import re
import argparse
def normalize_text(text: str) -> str:
"""简单文本清洗:去掉网址、多余空格"""
text = re.sub(r"http\S+", "", text)
text = re.sub(r"\s+", " ", text).strip()
return text
def generate_audio(text: str, output_path: str, seed: int = 42):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
chat = ChatTTS.ChatTTS()
chat.load(compile=False)
torch.manual_seed(seed)
wavs = chat.infer([normalize_text(text)], params_infer_code={
'spk_emb': None,
'temperature': 0.3,
'top_P': 0.7,
'top_K': 20,
'prompt': '[speed_1]'
})
sf.write(output_path, wavs[0], 16000)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--text", required=True, help="待合成文本")
parser.add_argument("--out", default="output.wav")
parser.add_argument("--seed", type=int, default=42)
args = parser.parse_args()
generate_audio(args.text, args.out, args.seed)
运行示例:
python tts_cli.py --text "你好,这是一条测试语音。" --out demo.wav
生产考量
-
并发处理
- ChatTTS 模型本身占显存 3.5G,再加安全余量,单卡 6G 只能跑一个实例。
- 使用 FastAPI + gunicorn 启动多进程时,设置
--workers=1,通过横向扩展容器而不是显存超卖。
-
错误处理与重试
- 捕获
RuntimeError: CUDA out of memory,退回到 CPU 模式并写入日志,不直接抛 500。 - 对网络下载权重环节加 tenacity 重试,最多 3 次,间隔 5s。
- 捕获
-
音频质量调优
- 温度 0.3→0.5 会让声音更活泼,但过高容易口吃。
- 长文本提前按句号切分,每段 ≤ 200 字,再批量 infer,可抑制首尾爆音。
- 输出后用 sox 做一键音量归一化:
sox input.wav -r 16000 -b 16 -c 1 output.wav norm -3
避坑指南
| 坑位 | 现象 | 快速解决 |
|---|---|---|
| 权重下载中断 | 卡在 99% 不动 | 手动下载到 models/ChatTTS/,确保 *.bin 与 *.json 成对出现 |
| 采样率混用 | 输出听起来像变声器 | 所有节点统一 16kHz,禁止 44.1k→16k 二次转码 |
| 显存泄漏 | 第二次推理 OOM | 节点里 with torch.no_grad() 包裹 infer,并手动 del wavs |
| 音色漂移 | 同 seed 不同卡声音不一致 | 固定 torch.manual_seed 前同步 CUDA_LAUNCH_BLOCKING=1 |
| 长文本爆音 | 末尾出现“啪”一声 | 按 200 字切分 + 静音 0.2s 拼接,再用 sox 淡入淡出 |
延伸思考
- 多语言:ChatTTS 已支持中英混输,把
[lang_en]或[lang_zh]写进prompt即可切换音素集。 - 情感化:在
params_infer_code加入[laugh_0.5][break_0.3]可让句子带笑或停顿,适合游戏配音。 - 实时流式:改 infer 为分块生成,配合 WebSocket 推送,每 0.5s 返回一段音频,实现“边打字边出声”。
- 声音克隆:官方将释出 speaker embedding 微调脚本,准备 30 条干净音频即可把“默认音色”换成指定主播。

把以上节点保存为模板,下次打开 ComfyUI 直接加载,就能一键复现整条语音合成管线。
先跑通离线 demo,再逐步把并发、监控、音色管理加上,一条可商用的 ChatTTS 工作流就稳稳落地了。
更多推荐



所有评论(0)