IndexTTS-2 TTS
Clone a Voice and Crank the Emotion Without Drifting It
- indextts_model
- reference_audio
- emotion_audio
- audio
Most TTS models make you choose: clone a voice or control emotion. IndexTTS-2 is the one that decouples them - the voice stays locked to your reference while you independently push the emotional dials. IndexTTS-2 TTS is the AIIA pack's synthesis node for it, and its selling point is how many ways you can drive emotion without touching the timbre.
How it works
You connect the indextts_model from the loader and give it text. The model runs zero-shot cloning using either a reference_audio sample or a built-in voice_preset (Female_HQ, Male_HQ, Female, Male - the HQ ones are better). Then emotion is applied as an 8-dimensional vector, which is what keeps it separate from the voice identity. Output is a single audio tensor.
Emotion has four sources, in this priority order (higher wins):
- Inline tags in the text - write
[happy] 今天天气真好and that sentence is generated with the happy vector while untagged sentences use the global setting. This is per-sentence emotion control, and it's the killer feature:[happy] 今天天气真好,阳光明媚! [sad] 但是我养的小猫走丢了,我好难过。 [calm] 不过我相信它一定会自己找到回家的路。 - The eight sliders -
happy,angry,sad,afraid,disgusted,melancholic,surprised,calm, each 0–1. They apply globally when no tags are present. use_emo_text- a built-in Qwen emotion model reads the text and infers the vector automatically (withemo_textas an override prompt).emotion_audio- a separate emotion reference clip, blended in atemo_alphastrength (0 = no emotion, 1 = full).
The inputs that matter
text- the script, with optional inline[Tag]markers. This is where 90% of the control lives.reference_audio- your cloning sample. Leave empty to usevoice_preset.emo_alpha- the master emotion-intensity dial. Here's the trap the README warns about: inline tags default to full-strength emotion (1.0), and at 1.0 you can get distortion, shouting, or a raspy "over-acted" voice. Droppingemo_alphato 0.6–0.8 keeps the timbre intact while still coloring the delivery. Start there.interval_silence/max_text_tokens_per_segment- long text gets split into segments with a pause (interval_silence, in ms) between them; the token cap controls how chunky the segments are.
Why you'd pick this over the pack's other TTS engines
If you're doing a character with shifting moods (narrator turning sad, then angry), IndexTTS-2's per-sentence tags beat a single global emotion knob hands down. The AIIA pipeline even wires it up automatically: AIIA Emotion Annotator can inject [happy]/[sad] tags into your podcast script, and AIIA Podcast Splitter's output is made for this node. Vs. the pack's own engine comparison: CosyVoice wins on dialect breadth and production stability, VibeVoice wins on long-form context - IndexTTS-2 wins on precise, decoupled emotion.
Install & troubleshooting
Install havvk/ComfyUI_AIIA via ComfyUI Manager or git clone into custom_nodes/, restart, and follow the loader's model setup (four sub-models in models/indextts2/). Missing sub-models mean first run silently re-downloads - slow and network-dependent. And that 3–5 minute FST compile on first load is normal; subsequent runs are fast. If output audio comes out slightly metallic or noisy, that's the BigVGAN upsample path - turn use_cuda_kernel off in the loader once and compare.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| indextts_model | INDEXTTS_MODEL | — | |
| text | STRING | 你好,这是一段 IndexTTS-2 语音合成测试。 | — |
| voice_preset | COMBO | Female_HQ | 4 options: Female_HQ, Male_HQ, Female, Male |
| reference_audioopt | AUDIO | Speaker voice reference. Leave empty to use voice_preset. | |
| emotion_audioopt | AUDIO | Optional emotion reference audio (separate from speaker voice). | |
| emo_alphaopt | FLOAT | 1.000–1 | Emotion blending strength (0=no emotion, 1=full emotion). |
| happyopt | FLOAT | 0.000–1 | — |
| angryopt | FLOAT | 0.000–1 | — |
| sadopt | FLOAT | 0.000–1 | — |
| afraidopt | FLOAT | 0.000–1 | — |
| disgustedopt | FLOAT | 0.000–1 | — |
| melancholicopt | FLOAT | 0.000–1 | — |
| surprisedopt | FLOAT | 0.000–1 | — |
| calmopt | FLOAT | 0.000–1 | — |
| use_emo_textopt | BOOLEAN | false | Auto-detect emotion from text using built-in Qwen emotion model. Overrides emotion sliders. |
| emo_textopt | STRING | Custom emotion text prompt (used with use_emo_text). Leave empty to use main text. | |
| interval_silenceopt | INT | 2000–2000 | Silence duration (ms) inserted between text segments for long text. |
| max_text_tokens_per_segmentopt | INT | 12030–500 | Max tokens per text segment. Lower = more segments, higher = longer per-segment generation. |
| use_randomopt | BOOLEAN | false | Enable random sampling (reduces voice cloning fidelity). |
| seedopt | INT | 0-1–2147483647 | Random seed. -1 = random. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |