Fish S2 Multi-Speaker Split TTS
One conversation, ten separate audio tracks for lip sync
- audio
- speaker_1_audio
- speaker_2_audio
- speaker_3_audio
- speaker_4_audio
- speaker_5_audio
- speaker_6_audio
- speaker_7_audio
- speaker_8_audio
- speaker_9_audio
- speaker_10_audio
Take the multi-speaker conversation node and add the one output it's missing for animation work, and you get this. Fish S2 Multi-Speaker Split TTS generates the same multi-voice dialogue as its sibling, but instead of handing you one mixed audio file it also gives you a separate track per speaker - each track holds that speaker's lines and digital silence everywhere else, all the same length as the combined audio. If you've ever tried to lip-sync a two-person scene and had to manually slice one wav into "who's talking now" chunks, you already know why that's worth a whole node.
This is the ComfyUI answer to the "generate voices, then drive mouths" pipeline the KB documents - the standard local talking-head chain is TTS → audio-driven avatar, and for multi-character scenes (Infinite Talk and friends) each mouth needs its own audio track to know when to move. The per-speaker isolation idea came from the community (@lazybuttalented suggested it), and it's the difference between "render a two-person conversation" and "render a two-person conversation where both faces move correctly."
How it works
Under the hood it's the multi-speaker node's generation loop - parse the script, generate each line with the right speaker's reference, pause between turns - plus a routing step. As each line finishes, it's appended to the speaking speaker's track while every other track gets a zero-padded segment of the same duration. The result: audio is the full conversation, and each speaker_N_audio output is an aligned, isolated stem. pause_after_speaker controls the silence between turns and applies to both the combined file and the tracks.
Inputs that matter
Inputs are identical to Fish S2 Multi-Speaker TTS, so everything you learned there carries over:
- num_speakers - 2 to 10, dynamic; raising it reveals more
speaker_N_audio/speaker_N_ref_textinputs. - speaker_N_audio - a 5–30s reference clip per voice. All required, or the run fails.
- text - dialogue in
[speaker_1]:/[speaker_2]:format, inline emotion tags allowed. - pause_after_speaker - silence between turns (0.4s default).
The outputs are the whole point: audio (the mix), plus speaker_1_audio through speaker_10_audio (AUDIO). Wire each speaker track to its own lip-sync node and keep audio as your master for the final render. You don't have to connect all ten - unused outputs are just empty tracks.
Shared pack knobs - model_path, precision, attention, temperature, keep_model_loaded - behave exactly as in the other Fish S2 nodes. Start on s2-pro-bnb-nf4 if you're under ~20GB of VRAM.
Install and gotchas
ComfyUI Manager → search "FishAudioS2" → install → restart, or git clone https://github.com/Saganaki22/ComfyUI-FishAudioS2.git into custom_nodes/. Dependencies auto-install at first startup; the model auto-downloads to ComfyUI/models/fishaudioS2/. Don't pip install fish-speech yourself (bundled, PyTorch-downgrade trap), and give it one restart before debugging load failures.
Realistic expectations, same as its sibling: this is turn-based dialogue with pauses, not overlapping conversation - each track is cleanly "this speaker, then silence," which is exactly what lip sync wants anyway. One tip for animation: if you're driving faces, keep pause_after_speaker at 0.3–0.4s so the "not speaking" moments read naturally on screen. And the usual license reminder - Fish Audio Research terms, non-commercial unless you buy a commercial license from Fish Audio.
If you're building multi-character talking-head videos in ComfyUI, this is the TTS node you want. It quietly removes the most fiddly manual step in the pipeline.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| model_path | COMBO | S2-Pro checkpoint folder name. | |
| text | STRING | [speaker_1]: Hello, I'm speaker one. [speaker_2]: And I'm speaker two! | Multi-speaker text. Use [speaker_1]:, [speaker_2]:, ... |
| language | COMBO | Language hint. | |
| device | COMBO | Compute device. | |
| precision | COMBO | Model precision. | |
| attention | COMBO | Attention kernel. | |
| max_new_tokens | INT | 00–4096 | Max acoustic tokens. 0 = auto. |
| chunk_length | INT | 200100–400 | Chunk length for synthesis. |
| temperature | FLOAT | 0.800.1–1 | Sampling temperature. |
| top_p | FLOAT | 0.800.1–1 | Top-p nucleus sampling. |
| repetition_penalty | FLOAT | 1.100.9–2 | Repetition penalty. |
| seed | INT | 00–2147483647 | Random seed. |
| keep_model_loaded | BOOLEAN | true | Keep model in VRAM between runs. |
| offload_to_cpu | BOOLEAN | false | Offload to CPU after generation. |
| compile_model | BOOLEAN | false | torch.compile (not on Windows). |
| pause_after_speaker | FLOAT | 0.40–2 | Seconds of silence after each turn. |
| num_speakers | COMBO | How many speakers (2-10). |
Outputs (11)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |
| speaker_1_audio | AUDIO | — |
| speaker_2_audio | AUDIO | — |
| speaker_3_audio | AUDIO | — |
| speaker_4_audio | AUDIO | — |
| speaker_5_audio | AUDIO | — |
| speaker_6_audio | AUDIO | — |
| speaker_7_audio | AUDIO | — |
| speaker_8_audio | AUDIO | — |
| speaker_9_audio | AUDIO | — |
| speaker_10_audio | AUDIO | — |