给一段几秒钟的录音,让模型用这个人的声音念出任意文字,今天已经不算稀奇。真正难的是后面几件事:

  • 中文多音字读错了,能不能直接指定拼音?
  • 只想借一个人的音色、另一个人的情绪,能不能把两者拆开?
  • 给视频配音时,能不能刚好念满 4.2 秒?
  • 模型从中文扩到日语、西班牙语后,会不会看到同一个汉字就串语言?
  • 在保持自然度的同时,能不能把几十 Hz 的自回归序列再压短一半?

IndexTTS 系列的演进,几乎就是沿着这些问题展开的。1.0 先把「好用、稳定、可纠音的零样本克隆」做起来;1.5 打磨稳定性和英语;2 把架构重组为 Text-to-Semantic(T2S)与 Semantic-to-Mel(S2M),加入时长和情感控制;2.5 再把帧率砍半、扩到四语种,并用 GRPO 做后训练。

这篇不只列功能,而是顺着数据真正走一遍:

文字怎么切成 token → 声音怎么切成 token → GPT 预测的究竟是什么 → token 又如何变回 mel 和波形。

截至 2026 年 7 月,官方主仓库公开提供 1.0、1.5 与 2 的模型入口;2.5 已有技术报告与演示,但还没有出现在官方仓库的模型下载表中。下文会把「论文方法」与「当前开源实现」分开说明。

一张图看懂四个版本

IndexTTS 1.02025-031.52025-05IndexTTS 22025-092.52026-01 报告可控克隆主干汉字 + 拼音 BPE25Hz 单码本GPT → BigVGAN2工程增强稳定性 ↑英语表现 ↑主范式不变架构重组50Hz 语义 tokenT2S + S2M时长 + 情感多语种高效率25Hz 语义 tokenZipformer + GRPO中英日西同一条 1.x 路线同一条 2.x 路线
IndexTTS 系列演进:1.0 建立可控零样本克隆主干,1.5 做工程增强,2 重构中间表示并加入时长与情感,2.5 转向多语种和高效率
版本时间核心变化公开状态
IndexTTS 1.02025-03中英 BPE、汉字—拼音混合、25Hz 单码本、Conformer-Perceiver、BigVGAN2权重与推理代码
IndexTTS 1.52025-05稳定性与英语表现增强权重与推理代码
IndexTTS 22025-0950Hz 语义 token、T2S + flow-matching S2M、音色—情感解耦、论文中的精确时长控制权重与推理代码;时长控制尚未在官方发布版启用
IndexTTS 2.52026-0125Hz 语义 token、Zipformer S2M、四语种、GRPO技术报告与演示

这条时间线里最重要的并不是模型越来越大,而是中间表示换了:

  • 1.x 让 GPT 预测偏声学的 VQVAE token,并把 GPT 隐状态直接交给 BigVGAN2;
  • 2.x 让 GPT 只负责聚焦内容的语义 token,再用独立的 flow-matching 模块补回音色、情绪和声学细节。

前者路径短、速度快;后者多走一步,却更容易把「说什么、谁在说、怎么说、说多久」拆开控制。

先建立一个正确的心智模型

现代 LLM-TTS 通常至少有两套 tokenizer:

  1. 文本 tokenizer:把汉字、拼音、英文子词和标点变成离散 ID;
  2. 语音 tokenizer:把连续声音压成每秒几十个离散 ID。

中间的自回归 Transformer 做的事情,和文本 LLM 很像:

p(s₁:ₜ | x₁:ₙ, c) = ∏ₜ p(sₜ | s<ₜ, x₁:ₙ, c)

其中 x 是文本 token,s 是语音 token,c 是参考音频提取出的说话人、情感或时长条件。模型每次猜下一个语音 token,直到生成结束符。

两套 tokenizer,两个完全不同的问题文本 tokenizer:所有版本的共同底座原始文字中英混合文本归一化数字 · 标点 · 缩写CJK 预切分保留拼音声调BPE12K 词表约 8,400 汉字 + 1,721 拼音 + 英文 word piece + 特殊符号IndexTTS 1.xIndexTTS 2 → 2.524kHz 波形→ melVAE encoder偏声学表示单层 VQ / FSQ8,192 类 · 25Hz语音波形自监督特征W2V-BERT第 17 层RepCodec · 单层 F-VQ8,192 类 · 50Hz → 25Hztoken 仍承担较多声学信息后级路径短,控制维度较纠缠token 更聚焦内容与发音音色与情感交给独立条件和 S2M同样是「单码本」,输入特征与下游解码方式不同,token 承担的信息也完全不同
IndexTTS 的两层离散化:文本侧始终以 12K BPE 为主;语音侧从 1.x 的 25Hz 声学 VQVAE,演进到 2 的 50Hz 语义 codec,再在 2.5 压回 25Hz

容易混淆的一点是:语音 token 不等于最终声音。一个 ID 只是在码本里选了一个向量,它通常丢掉了大量细节。音色、混响、气声、细微韵律要么放进 token,要么由参考音频和后级生成器补回来。IndexTTS 的版本演进,本质上就是不断重新分配这些信息该由谁负责。

文本 tokenizer:不用全量 G2P,但保留拼音控制

IndexTTS 1 的论文说「移除 G2P,直接输入原始文本」,同时又说「使用汉字—拼音混合建模」。这并不矛盾:

  • 它不再要求前端把每个汉字强制转换成音素;
  • 正常输入可以一直写汉字,让模型从上下文学习读音;
  • 遇到多音字或生僻字时,用户可以只把那个位置改写成带声调数字的拼音。

整个文本前端可以画成:

原始文本
  ↓ 文本归一化(数字、英文缩写、标点等)
中文字符预切分
  ↓
SentencePiece BPE
  ↓
12,000 个文本 token

词表包含约 8,400 个汉字、1,721 个带声调拼音、英文 word piece 和若干特殊符号。论文里的例子很直观:

原句:晕眩是一种感觉,I want to go to the supermarket!

混合输入:
晕 XUAN4 是 一 种 GAN3 觉,I WANT TO GO TO THE SUPERMARKET!

BPE:
_晕, _XUAN4, _是, _一, _种, _GAN3, _觉, ...,
_SUPER, M, AR, KE, T, !

这里 XUAN4 明确告诉模型「眩」读 xuàn,GAN3 则指定「感」的读音。推理代码还会把 ju / que / xun 一类拼音中的 u / ü 规范成 v 表示法,防止文本归一化破坏用户写下的声调。

为了让模型在训练时真的学会接住这种输入,IndexTTS 会对 50% 的训练样本做增强,并在其中随机选 20% 的非多音字替换成拼音。于是同一个模型同时见过:

「重庆银行」
「重 QING4 银行」
「CHONG2 庆 YIN2 行」

这比纯 G2P 前端多一层弹性:日常输入保持自然文字,真正读错时才人工接管局部发音。论文在 2,500 条多音字测试上发现,纯汉字输入有 465 条读错;加入正确拼音后,其中 437 条得到纠正,也就是纠正了约 94% 的原始错误。

IndexTTS 2 沿用了同一套 12K BPE。2.5 在扩展日语和西班牙语时,重点也不是发明新的通用 tokenizer,而是给文本 token 增加更明确的语言身份;后面会详细讲。

1.x 的语音 tokenizer:25Hz 单码本,追求短路径

从 24,000 个采样点压到 25 个 token

IndexTTS 1.x 的输入音频为 24kHz。语音 VAE 先把 mel 频谱编码成连续向量,再通过单个 VQ 码本量化:

wave₂₄ₖ → mel → zₜ → argminₖ ‖zₜ − eₖ‖₂ → sₜ
  • 帧率:25Hz,也就是一个 token 大致覆盖 40ms;
  • 码本:约 8,192 个条目;
  • VAE:约 50M 参数;
  • 码本数:1,而不是 VALL-E 那样的多层 RVQ。

假设一句话长 6 秒,原始波形有 144,000 个采样点,经过 tokenizer 后只剩约 150 个离散 ID。GPT 预测 150 步,当然比直接预测十几万个波形点现实得多。

VQ 和 FSQ:结论不是「FSQ 一定更好」

普通 VQ 容易发生 codebook collapse:8,192 个格子里只有一小部分经常被用到。IndexTTS 对 VQ 与 FSQ(Finite Scalar Quantization)做了对照:

  • 在 6,000 小时数据上,VQ 的码本利用率只有约 55%;
  • 数据增到 34,000 小时后,VQ 与 FSQ 都能接近 100% 利用率。

这组实验给出的工程结论很有价值:FSQ 的确更不容易塌缩,但足够大、足够多样的数据也能把 VQ 码本喂活。不能只看量化器名字,训练数据规模同样决定离散空间是否被充分使用。

它不是「token ID → codec decoder → 波形」

IndexTTS 1.x 最特别的一步,是没有用一个传统 codec decoder 从离散 ID 重建波形。GPT 在预测语音 token 时会产生连续隐藏状态 hₜ,系统直接使用这串隐藏状态:

25Hz GPT hidden states
  → 插值到 100Hz
  → 与说话人 embedding 一起送入 BigVGAN2
  → 24kHz 波形
IndexTTS 1.x:用离散目标训练,用连续 hidden 解码目标文字汉字 / 拼音 / 英文12K BPE token[BT] ... [ET]Decoder-only GPT自回归预测 25Hz token8,192 类训练监督参考音频无需转写Conformer+ PerceiverGPT hidden:25Hz → 100Hz → BigVGAN2连续细节 + speaker condition → 24kHz 波形离散 ID 约束「生成什么」;连续 hidden 保留「怎么发出这段声音」
IndexTTS 1.x:参考音频被压成全局说话人条件,文本经 GPT 生成 25Hz token;最终解码使用更富信息的 GPT 隐状态,而不是只依赖离散 token ID

这是一种聪明的折中:

  • 离散 ID 给 GPT 一个清晰、稳定的分类目标;
  • 连续隐藏状态没有被 8,192 选 1 的量化瓶颈完全截断,能带更多声学线索;
  • BigVGAN2 一步到波形,省去扩散 / flow matching 的多步求解。

也要看到代价:内容、韵律和部分声学细节仍挤在同一条 GPT 表示里。模型很难显式地说「这部分只管音色,那部分只管情绪」。这正是 2.0 要重构的地方。

1.x 的主干:为什么克隆声音不需要参考文本

IndexTTS 1.x 的 GPT 是 decoder-only Transformer。以 1.5 公开配置为例:

  • 24 层、隐藏维度 1,280、20 个注意力头;
  • 12,000 个文本 token;
  • 8,192 个语音码,加开始 / 结束两个特殊码;
  • 最多 600 个文本 token、800 个语音 token;
  • 参考音频由 Conformer + Perceiver 压成条件序列。

训练序列可简化为:

speaker_condition,
[BT], text_tokens, [ET],
[BA], speech_tokens, [EA]

[BT]/[ET] 是文本边界,[BA]/[EA] 是音频边界。模型看到参考音频提取出的 speaker_condition 和目标文本后,就开始逐 token 生成声音。

这条设计和 VALL-E 式 prompting 的差别在于,它不需要把「参考音频的转写 + 参考音频 token」一起拼进上下文。优点有三个:

  1. 用户只需提供录音,不必提供参考文本;
  2. 跨语言克隆时,不必先用多语种 ASR 猜出参考音频说了什么;
  3. prompt 再长也不会线性挤占 GPT 的 token 上下文,Perceiver 负责把它压缩。

Conformer 同时看局部声学模式与长程上下文,Perceiver 再用固定数量的 latent 去读取可变长参考音频。相比把整段 prompt token 原样塞给 GPT,这更像先做一份「说话人摘要」。

IndexTTS 1.5 改了什么

官方只明确宣布:1.5 显著增强稳定性和英语表现;没有为它发布新的技术论文,也没有声明更换文本 tokenizer、语音 codec 或主干范式。公开的 1.5 配置仍是上面这条 25Hz VQVAE → GPT → BigVGAN2 路线。

因此,更稳妥的理解是:1.5 是 1.x 架构上的数据、训练和工程迭代,而不是一次方法论换代。 如果资料没有公开,就不应根据结果反推一套并不存在的结构改动。

IndexTTS 2:从「声学 token」转向「语义 token」

IndexTTS 2 把系统拆成三个核心模块:

  1. T2S(Text-to-Semantic):自回归生成语义 token;
  2. S2M(Semantic-to-Mel):用 flow matching 并行生成 mel;
  3. BigVGANv2:把 mel 变成波形。
IndexTTS 2:AR 管内容,NAR 补声学文本 BPE说什么Timbre prompt谁在说Style prompt怎么说Token 数 L说多久 · 可选T2S · AR Transformer24 层 · 1,280 hiddennext semantic token内容 / 顺序 / 停顿50Hz 语义 tokenRepCodec embeddingGPT latent发音上下文融合 + Length regulator语义帧 → mel 帧S2M · NARFlow MatchingU-DiT+ 参考 mel+ speaker style目标 mel80 binsBigVGANv2→ 波形参考音频还向 S2M 提供 mel / speaker style情感先影响 T2S 的语义生成,再体现到韵律离散语义 token 是骨架,GPT latent 与参考音频把骨架还原成具体声音
IndexTTS 2 完整数据流:T2S 只生成语义 token,S2M 再结合 GPT latent、音色参考与 mel prompt 补回声学细节,最后由 BigVGANv2 合成波形

2.0 的 audio tokenizer 到底是什么

它不再从 mel 频谱直接训练一个偏声学的 VQVAE,而是复用 MaskGCT 的语义 codec 路线:

参考 / 目标语音
  → Wav2Vec2-BERT 2.0
  → 第 17 层连续表征
  → 均值方差归一化
  → RepCodec + 单层 Factorized VQ
  → 8,192 类语义 token(50Hz)

官方开源配置中的 RepCodec 使用:

  • 单个 8,192 大小的码本;
  • 1,024 维输入特征;
  • 8 维 factorized codebook 空间;
  • 50Hz 输出帧率。

它叫「语义 token」,因为输入不是原始 mel,而是自监督语音模型的中间表示。这种表示更关注音素、词和内容结构,弱化了录音设备、混响和部分音色细节。

这恰好适合新的分工:

  • T2S 专心保证「字有没有念对、顺序对不对」;
  • 音色由独立 timbre prompt 提供;
  • 情感由独立 style prompt 提供;
  • S2M 负责把这些条件重新揉成细腻的声学结果。

T2S:一个更大的 GPT 式语义预测器

官方开源配置中的 T2S 为 24 层、隐藏维度 1,280、20 个注意力头(论文未列出结构参数),文本词表仍是 12K,语义码本仍是 8,192 加两个边界码。

输入条件包括:

  • 文本 BPE token;
  • 参考音频经过 speaker perceiver 得到的音色条件;
  • style prompt 经过 emotion perceiver 得到的情感条件;
  • 可选的目标语义 token 数;
  • 已生成的语义 token。

它仍然是标准 next-token prediction,只不过下一枚 token 现在更偏「说了什么」,不必独自扛起最终音质。

S2M:为什么还要把 GPT latent 加回来

如果只把 8,192 类语义 ID 交给下游,强情感语音里容易出现含混、吞字。IndexTTS 2 又把 T2S 的连续隐藏状态拿了回来,与语义 codec embedding 相加,再交给 S2M:

增强语义表示 s̃ₜ = Emb(sₜ) + MLP(hₜ)

训练时会以一定概率混合这两路信息。可以把它理解成:

  • 离散 token 是「课程提纲」,稳定但粗;
  • GPT latent 是「讲课笔记」,保留文本上下文与发音细节;
  • 二者合起来,S2M 才不容易在激烈情绪下只顾表演、忘了咬字。

之后 length regulator 把 50Hz 语义序列扩到 mel 的时间分辨率。U-DiT 作为 conditional flow matching 的速度场网络,从噪声出发,经若干 ODE 步生成目标 mel。公开推理代码默认使用 25 步,再由 22.05kHz BigVGANv2 输出波形。

这里的「AR + NAR」混合非常关键:

  • T2S 是 AR,擅长内容一致性、自然停顿和开放式时长;
  • S2M 是 NAR,可以并行补全声学细节,不必再自回归生成多层 codec。

精确时长控制:让终点和位置使用同一把尺

自回归模型通常只能不断生成,直到自己吐出结束符。想让它刚好生成 L 个语义 token,最朴素的方法是告诉它一个长度数字,但模型未必理解「这个数字」和「我当前走到第几步」之间的关系。

IndexTTS 2 的关键做法是共享时长 embedding 与语义位置 embedding 的参数:

e_duration(L) = e_position(L)

也就是说,「目标长度是 200」与「走到第 200 个位置」来自同一张坐标表。模型一开始拿到终点坐标,生成过程中又不断看到当前位置坐标,二者天然可比较。

目标长度与当前位置,共用一张坐标表目标 token 数 L例如 L = 200当前生成位置 t1, 2, 3, ...共享 Position Embedding12…LAR T2S终点:e(L)当前位置:e(t)到点生成 EOS30% 训练样本:e(L) = 0 → 保留自由时长模式「我要走到哪里」「我已经走到哪里」
时长控制的核心:目标长度 L 与每一步位置 t 查询同一张 embedding 表;模型知道终点坐标,也知道自己走到了哪里

为了同时保留两种模式,训练时有 30% 概率把长度条件置为零:

  • 有长度条件:严格生成指定 token 数,适合配音对口型;
  • 无长度条件:自由决定何时结束,更好地复刻参考音频的自然语速与停顿。

论文还会随机调整目标语音和 speaker prompt 的速度,避免模型把「某个说话人」和「固定语速」错误绑定。报告中的 token 数量误差极低,说明模型确实学会了停在指定位置。

不过要注意一个现实边界:官方仓库发布 IndexTTS 2 时明确写着,这项时长控制尚未在该发布版中启用。所以它是论文中已经验证的方法,不等于当前官方 infer_v2.py 已提供一个可直接填写秒数的参数。

帧率也决定长度控制的时间刻度。2.0 为 50Hz,一个语义 token 约 20ms;2.5 压到 25Hz 后,一个 token 约 40ms。最终波形仍要经过 length regulator 和 S2M,但 token 数已经给出稳定的全局时长锚点。

情感—音色解耦:借 A 的嗓子,学 B 的情绪

普通零样本 TTS 从同一段 prompt 同时提取音色、语速和情绪。如果参考音频里的人很悲伤,模型往往把「这个人的声音」和「悲伤」粘在一起。

IndexTTS 2 使用两条条件支路:

  • timbre prompt:回答「谁在说」;
  • style prompt:回答「怎么说」。
把「谁在说」和「怎么说」拆成两路Timbre prompt A目标音色Style prompt B目标情绪Speaker Perceiver保留说话人身份Emotion Perceiver保留韵律与能量Speaker embedding「像 A」Emotion embedding「像 B 的情绪」T2S + S2M重新融合A 的嗓子B 的情绪GRL + Speaker Classifier反向梯度:让说话人更难被猜出GRL 不是删除情感,而是对抗性地压低情感向量里的说话人身份信息
音色与情感分路:speaker perceiver 保留说话人身份,emotion perceiver 在 GRL 对抗约束下尽量去掉说话人信息,最后在 T2S 与 S2M 中重新融合

情感编码器后面接一个 Gradient Reversal Layer(GRL)和辅助说话人分类器。前向传播时 GRL 什么也不做,反向传播时却把梯度乘上负数:

∂ GRL(x) / ∂x = −λI

分类器努力从情感 embedding 猜出说话人,情感编码器则被反向梯度推着让这件事变难。最终得到的向量更倾向于保留高低起伏、能量和节奏等情感线索,少带说话人身份。

训练分三阶段:

  1. 先在全量数据上做基础训练,只带音色与时长条件,建立基本合成能力;
  2. 再在 135 小时情感数据上微调:冻结 speaker perceiver,训练 emotion perceiver,并借助 GRL 与说话人分类器做对抗解耦;
  3. 最后冻结所有 conditioner,在全量数据上再微调一轮,保住通用清晰度。

推理时可以:

  • 不传 style prompt:复刻 timbre prompt 自带的情绪;
  • 传另一段情感录音:A 的音色 + B 的情绪;
  • 直接给情感向量;
  • 用自然语言描述,让一个小型 Qwen 模型先推断情感分布。

论文用约 1,000 条 DeepSeek-R1 生成样本,对 Qwen3-1.7B 做 LoRA 微调,把文本描述映射为标准情感概率,再对情感原型向量加权求和。需要注意论文与公开 API 的标签稍有差异:

  • 论文示例使用愤怒、快乐、恐惧、厌恶、悲伤、惊讶、中性 7 类;
  • 当前公开接口暴露 8 维:happy, angry, sad, afraid, disgusted, melancholic, surprised, calm。

因此,复现论文时不要想当然地把论文里的 7 维顺序直接传给开源 API;应以正在使用的代码版本和接口文档为准。

IndexTTS 2.5:把序列压短,把语言身份说清

2.5 保留 T2S → S2M → BigVGAN 的总体框架,集中改四件事。

IndexTTS 2.5:四个目标,四处定点改造1234Semantic codec compression50Hz25Hz序列减半 · T2S RTF 0.232 → 0.119S2M backboneU-DiTZipformerS2M RTF 0.078 → 0.017Multilingual identity句级边界逐 token 语言向量自然语言指令中文 · 英文 · 日语 · 西班牙语GRPO post-training每条文本采样 4 个候选ASR WER 排名 → 组内更新优化内容正确性与自然度总 RTF:0.310 → 0.136,约 2.28× 加速
IndexTTS 2.5 的四个升级:50Hz 压到 25Hz、U-DiT 换成 Zipformer、增加三种语言身份建模、用基于 ASR WER 的 GRPO 后训练 T2S

1. 语义 codec 从 50Hz 压到 25Hz

自回归注意力的代价随序列长度快速增长。把 10 秒语音从约 500 个 token 压成约 250 个 token,不只是少生成一半:

  • KV cache 变小;
  • T2S 的注意力计算下降;
  • 训练样本能容纳更长语音;
  • 推理的串行步数直接减半。

在相同硬件上,论文报告 T2S RTF 从 0.232 降到 0.119。

2. S2M 从 U-DiT 换成 Zipformer

U-DiT 擅长多尺度生成,但对一维语音序列并不便宜。Zipformer 原本就为高效语音建模设计,使用不同时间分辨率的 encoder stack,在重要层保持细粒度、其他层压缩序列。

替换后 S2M RTF 从 0.078 降到 0.017;T2S 与 S2M 合计从 0.310 降到 0.136,整体约快 2.28 倍。主观偏好测试里,Zipformer 版本也以 56% 对 40% 胜过 U-DiT,说明这次提速没有靠明显牺牲听感换来。

3. 四语种与三种语言建模策略

2.5 支持中文、英文、日语和西班牙语。难点不只是扩词表:日语和中文共享大量汉字,同一个字符在不同语言里发音完全不同。

论文比较了三种做法:

策略做法优点代价
Boundary-Aware整句前后加 <ZH>...</ZH> 一类边界最简单长句中语言约束会逐渐变弱
Token-Level Concatenation每个文本 token 都拼接语言 embedding控制最稳,中文 / 英文 / 西语综合最好需要前端逐 token 判断语言
Instruction-Guided在正文前加入「请用日语朗读」一类指令不依赖外部语言标签器,日语 WER 最好依赖 prompt 设计,混合语言时有冗余

这三种方案其实代表三个粒度:整句打标签、每个 token 打标签、让模型从自然语言指令理解标签。论文最终显示,没有一种策略在所有指标上全胜;工程选型取决于是否需要 code-switching、前端复杂度能否接受,以及目标语言的文字系统。

4. 用 GRPO 优化「念得对不对」

2.5 对每个文本随机采样 4 条语音,用冻结 ASR 计算 WER,把低 WER 的候选视为高奖励,再用 GRPO 提高它相对于同组其他候选的概率。

这不是让模型追逐一个主观的「好听分」,而是先把奖励锚定在可自动验证的内容正确性上。论文中的英语和日语 RL 版本都降低了 WER。它也展示了语音后训练的一个实用方向:生成 → ASR 回听 → 组内比较 → 更新 TTS。

数据规模如何跟着目标变化

版本训练语音语种构成情感数据
1.034K 小时中文 25K + 英文 9K未单独强调
2.055K 小时中文 30K + 英文 25K135 小时 / 361 位说话人
2.5约 100K 小时中文 30K + 英文 25K + 日语 42K + 西语 2.9K135 小时

2.5 还公开了一条更完整的数据流水线:VAD 与事件分类 → ASR、说话人分离和标点恢复 → 必要时用 Demucs 分离人声 → 按说话人、语义连贯性和静音合并片段 → 音频质量与转写质量双重过滤。每段最终限制在 25 秒内。

这部分很容易被架构图掩盖,却决定了模型是否「工业可用」。一个 8,192 大小的码本能不能被充分使用,多语种是否串音,标点能不能稳定控制停顿,都和数据清洗及伪标签质量直接相关。

跑起来:IndexTTS 2 的最小用法

官方目前推荐使用 uv 管理环境:

git clone https://github.com/index-tts/index-tts.git
cd index-tts
git lfs pull

uv sync --all-extras

uv tool install "huggingface-hub[cli,hf_xet]"
hf download IndexTeam/IndexTTS-2 --local-dir=checkpoints

最小推理代码:

from indextts.infer_v2 import IndexTTS2

tts = IndexTTS2(
    cfg_path="checkpoints/config.yaml",
    model_dir="checkpoints",
    use_fp16=True,
    use_cuda_kernel=False,
    use_deepspeed=False,
)

tts.infer(
    spk_audio_prompt="voice.wav",
    text="重庆的重读 CHONG2,这里我希望明确控制读音。",
    output_path="output.wav",
)

换一段情感参考音频:

tts.infer(
    spk_audio_prompt="speaker_a.wav",
    emo_audio_prompt="emotion_b.wav",
    emo_alpha=0.8,
    text="这句话保留 A 的音色,但借用 B 的情绪。",
    output_path="emotion-transfer.wav",
)

或者直接用自然语言描述情绪:

tts.infer(
    spk_audio_prompt="speaker_a.wav",
    text="我就知道,你一定会回来。",
    emo_text="先压住惊喜,随后逐渐放松,最后带一点笑意。",
    use_emo_text=True,
    emo_alpha=0.6,
    output_path="emotion-by-text.wav",
)

参考音频不需要转写,但质量很重要:尽量使用单人、少混响、无背景音乐、音量正常的几秒到十几秒录音。模型可以从脏 prompt 里模仿出「像」,却也可能把噪声、房间声和口癖一起当成目标特征。

怎么选版本

选 1.5,如果你更在意

  • 架构较短、依赖更少;
  • 中英零样本克隆和拼音纠音;
  • Apache 2.0 许可下的再开发;
  • 不需要独立情感参考或论文级精确时长。

选 2,如果你更在意

  • 强情感表达;
  • 音色与情感分别控制;
  • 文本描述情感;
  • 更高的零样本相似度与内容稳定性;
  • 接受更重的 T2S + flow-matching S2M 推理链。

关注 2.5,如果你更在意

  • 日语、西班牙语与跨语言情感迁移;
  • 25Hz 语义 token 带来的更高推理效率;
  • Zipformer S2M 与 GRPO 后训练;
  • 但可以等待正式权重和代码发布,再谈生产落地。

几个不能忽略的边界

  1. 论文能力不等于开源接口能力。 IndexTTS 2 的精确时长控制在论文中成立,但官方发布说明明确标注尚未启用。
  2. 它不是原生语音编辑模型。 系统擅长从文本重新合成,不等于能在原录音中无缝替换任意几个字。
  3. 长文本仍需分段。 当前 WebUI 和推理代码会按文本 token 分段,再插入段间静音;分段位置会影响跨句韵律。
  4. AR 采样会带来波动。 top_p、top_k、temperature 和随机采样能增加表现力,也可能降低克隆相似度或内容稳定性。
  5. 许可发生了变化。 1.x 仓库标签使用 Apache 2.0;IndexTTS 2 使用 bilibili 自定义模型许可,其中包含大规模产品 / 营收阈值、下游分发与模型改进用途等条款。商业使用前应阅读当前 LICENSE,而不是沿用对 1.x 的印象。
  6. 声音克隆要有授权。 技术上只需要几秒录音,不代表可以绕过说话人的知情同意、人格权和平台规则。

写在最后

回看整个系列,IndexTTS 最值得学的不是某个单独模块,而是它对「信息应该放在哪里」的持续调整:

  • 文本侧不用全量 G2P,把自然输入和局部拼音纠错放在同一词表;
  • 1.x 用 25Hz 单码本和 GPT hidden → BigVGAN2,换来短而直接的生成路径;
  • 2.0 把中间层改成语义 token,让内容、音色、情感和声学重建各司其职;
  • 共享长度—位置 embedding,让 AR 模型第一次有了清晰的终点坐标;
  • 2.5 再把语义序列压回 25Hz,用 Zipformer 和 GRPO 同时处理效率与准确率。

Audio tokenizer 从来不只是一个压缩器。它决定自回归模型每秒要走多少步,也决定音色、韵律、情感和内容究竟纠缠在一起,还是能被后级模块重新组合。

如果只记住一句话,可以是:

IndexTTS 1.x 在做「短路径的声学 token TTS」,2.x 则转向「语义 token 负责说对,flow matching 负责说像、说得有情绪」。

这也解释了为什么 2.0 看起来更复杂,却能长出时长控制和情感解耦;以及为什么 2.5 的第一刀仍然砍向 tokenizer 帧率——在自回归语音模型里,表示方式往往比堆多少层网络更决定上限。

参考资料