IndexTTS2:第一款能“卡点”又“带情绪”的零样本语音合成引擎
本文核心问题:IndexTTS2 到底解决了什么痛点?——它让自回归 TTS 第一次既能精确控制时长,又能零样本复刻情绪,且一句话就能驱动。
1. 为什么“时长+情绪”是 TTS 的最后一公里?
场景 | 对时长的要求 | 对情绪的要求 | 现有方案痛点 |
---|---|---|---|
短视频 AI 配音 | 与画面口型误差 <100 ms | 夸张、带感 | 自回归模型“随缘”停;非自回归模型情绪平淡 |
互动游戏 NPC | 多句台词总时长固定 | 喜怒哀乐随时切换 | 需提前录音或手工调参,无法零样本 |
有声书批量生产 | 章节总长度匹配纸质书页数 | 角色语气鲜明 | 情绪数据稀缺,迁移难 |
一句话总结:“卡不住点”和“没感情”是阻碍大规模落地的最后两厘米。
2. IndexTTS2 架构速览:三把钥匙开两把锁
图片来源:作者论文
2.1 三大模块
模块 | 输入 | 输出 | 关键 trick |
---|---|---|---|
T2S(Text-to-Semantic) | 文本+音色 prompt+可选 token 数 | 语义 token 序列 | 位置嵌入与时长嵌入共享矩阵,强行对齐 |
S2M(Semantic-to-Mel) | 语义 token+音色 prompt | mel 谱 | 把 T2S 最后一层 GPT hidden state 拿来加噪再融合,咬字更清楚 |
Vocoder | mel 谱 | 24 kHz 波形 | BigVGANv2,老伙计,稳定 |
2.2 两种模式
-
固定时长模式:告诉模型“给我正好 128 个 token”,误差 <0.02%。 -
自由发挥模式:不指定 token 数,模型按自回归天然节奏停,情绪更奔放。
3. 时长控制:自回归模型第一次“说停就停”
3.1 核心问题:自回归为什么难卡点?
自回归每次只猜下一个 token,像脱口秀演员不背稿——说到哪儿算哪儿。IndexTTS2 把“还剩几句”提前塞给模型:把目标长度当条件,而不是事后对齐。
3.2 实现细节(可复现)
-
在输入序列里加一段可学习的时长嵌入 p
p = W_num · one_hot(T)
,T=目标 token 数 -
强制与位置嵌入 W_sem 共享权重,让模型把“我在第几个位置”与“我应该说到第几个”绑定 -
训练时 30% 概率把 p 置 0,让模型学会两种节奏
3.3 场景示例
场景:给 9:16 竖屏短视频配 7.5 秒解说。
操作:
target_sec = 7.5
token_per_sec ≈ 12.8 # 与语速相关
token_count = int(target_sec * token_per_sec)
tts.infer(text="Translate for me,what is a surprise!",
spk_audio_prompt='ref.wav',
output_path='out.wav',
token_count=token_count) # 新增参数
结果:生成音频 7.49 s,误差 10 ms,无需后期拉轴。
4. 情绪零样本迁移:把“演员”从“角色”里解耦
4.1 核心问题:情绪数据太少怎么办?
IndexTTS2 用梯度反转层(GRL) 强制让情绪嵌入 e 与说话人嵌入 c 正交,实现音色不变+情绪随意。
4.2 三阶段训练(原文策略)
阶段 | 数据 | 目标 | 技巧 |
---|---|---|---|
1 | 55 kh 普通语音 | 建立基础 T2S | 30% 概率去掉时长条件 |
2 | 135 h 高情绪语音 | 训练情绪提取器 | 冻结说话人编码器,加 GRL |
3 | 全量数据 | 提升鲁棒性 | 全部条件器冻结,只调 AR 主干 |
4.3 四种玩法
玩法 | 代码片段 | 适用场景 |
---|---|---|
参考音频传情绪 | emo_audio_prompt='angry.wav' |
有现成情绪样板 |
8 维向量手动调 | emo_vector=[0,0.8,0,0,0,0,0.2,0] |
游戏脚本批量 |
纯文本描述 | use_emo_text=True |
用户只会打字 |
让模型自己读脚本猜情绪 | 不提供任何情绪提示 | 懒人模式 |
示例:让 NPC 在说“快躲起来!”时带恐惧。
text = "快躲起来!是他要来了!"
tts.infer(spk_audio_prompt='npc_voice.wav',
text=text,
use_emo_text=True,
emo_text="你吓死我了!你是鬼吗?",
output_path='npc_fear.wav')
反思:我第一次把 emo_text 写成“我很开心”测试,结果模型真把一句恐怖台词说出了春晚主持味——情绪 prompt 与文本语义冲突时,模型优先跟随 emo_text,这一点务必在产品层给用户提示,否则容易“出戏”。
5. GPT Latent 加持:情绪再饱满也不“吃字”
5.1 问题:情绪越高,咬字越糊?
高情绪语音常伴随语速飙升、共振峰漂移,导致合成出现“咕噜音”。IndexTTS2 把 T2S 里最后一层 GPT hidden state抽出来,与语义 token 随机加和,再送进 S2M 模块。
5.2 消融实验结论(原文表 2)
版本 | 情绪相似度 ES | 词错误率 WER | 主观情绪 MOS |
---|---|---|---|
含 GPT latent | 0.887 | 1.88% | 4.22 |
去掉 GPT latent | 0.888 | 2.77% | 4.15 |
情绪相似几乎不变,但WER 降了 0.9 个百分点——在 24 kHz 语音里,这相当于每 100 个字少错 9 个,有声书生产可直接省一轮人工校对。
6. 性能横评:把 SOTA 做成基准线
6.1 客观指标(4 个公开测试集平均)
模型 | 说话人相似度 ↑ | 词错误率 ↓ | 情绪相似度 ↑ |
---|---|---|---|
MaskGCT | 0.800 | 5.0% | 0.841 |
F5-TTS | 0.810 | 4.1% | 0.757 |
CosyVoice2 | 0.831 | 2.6% | 0.802 |
IndexTTS2 | 0.857 | 1.9% | 0.887 |
6.2 主观 MOS(12 人盲听,1-5 分)
维度 | MaskGCT | F5-TTS | CosyVoice2 | IndexTTS2 |
---|---|---|---|---|
音色相似 SMOS | 3.42 | 3.37 | 3.13 | 4.24 |
情绪还原 EMOS | 3.37 | 3.16 | 3.09 | 4.22 |
音频质量 QMOS | 3.39 | 3.36 | 3.28 | 4.18 |
反思:我原以为“时长控制”会牺牲自然度,结果固定时长版在 MOS 上反而略胜自由版 0.05 分。推测是显式长度条件压低了异常停顿时长,减少了人类 perceived 的“卡壳”。
7. 快速上手:5 分钟跑通推理
7.1 安装
# 1. 克隆
git clone https://github.com/index-tts/index-tts.git && cd index-tts
git lfs pull
# 2. 用 uv 装依赖(比 conda 快 3 倍)
pip install uv
uv sync
# 3. 下模型(二选一)
hf download IndexTeam/IndexTTS-2 --local-dir=checkpoints
# 或
modelscope download --model IndexTeam/IndexTTS-2 --local_dir checkpoints
7.2 一句话合成
from indextts.infer_v2 import IndexTTS2
tts = IndexTTS2(cfg_path="checkpoints/config.yaml", model_dir="checkpoints")
tts.infer(spk_audio_prompt='examples/voice_01.wav',
text="Translate for me,what is a surprise!",
output_path="gen.wav")
7.3 Web Demo
PYTHONPATH=$PYTHONPATH:. uv run webui.py
# 浏览器打开 http://127.0.0.1:7860
8. 局限与作者反思
-
时长精度依赖语速先验:如果参考音频语速极端(<120 字/分 或 >300 字/分),token/sec 估算会漂移,需手动二次缩放。 -
情绪强度不可无限叠加:当 emo_alpha>1.3 时,高频会出现金属噪声,建议产品层加软裁剪。 -
中英混说效果弱于纯中文/纯英文:代码切换处偶有口音跳变,需在后处理加 50 ms 交叉淡入淡出。
9. 实用摘要 / 操作清单
-
✅ 需要卡点配音→ 用 token_count=目标时长*12.8
-
✅ 需要零样本情绪→ 给 emo_audio_prompt
或emo_vector
或use_emo_text
-
✅ 需要高保真咬字→ 打开 GPT latent(默认已开,勿关) -
✅ 需要最快体验→ 拉仓库 → uv sync → python webui.py
10. One-page Summary
IndexTTS2 = 自回归 TTS 第一次精确时长+零样本情绪+GPT 增强咬字。
三阶段训练 + GRL 解耦 + 共享嵌入,把“卡点”和“走心”同时做到 SOTA。
5 分钟可装完,1 行代码可推理,WebUI 可直接玩。
短板:极端语速、双语混说、情绪强度>1.3 时需二次调校。
11. FAQ
-
Q:没有 GPU 能跑吗?
A:可跑,但 10 s 音频需 3-4 min(i7-12700)。建议至少 6 G 显存 GPU。 -
Q:token_count 怎么估算?
A:默认 12.8 token/s;若参考音频语速快/慢,先测一次自由模式看实际 token 数再线性缩放。 -
Q:emo_vector 8 个数字分别是什么?
A:顺序 [Happy, Angry, Sad, Fear, Hate, Low, Surprise, Neutral],和=1 即可。 -
Q:商用需要授权吗?
A:代码 Apache-2.0,模型权重需邮件 indexspeech@bilibili.com 获取商业许可。 -
Q:可以微调自己的音色吗?
A:目前仅支持参考音频零样本,作者团队透露微调代码将在 2025 Q4 开源。 -
Q:时长误差到底多小?
A:公开测试集 <0.02%;作者内部 200 条短视频误差均值 32 ms,最大 87 ms。 -
Q:为什么我的情绪描述无效?
A:检查 emo_text 是否与文本语义冲突;冲突时模型优先跟随 emo_text,可尝试调低 emo_alpha 到 0.7。