Fish S2 Multi-Speaker TTS
Hold a whole podcast argument inside one node
- audio
The single-speaker Fish S2 nodes are already good. Fish S2 Multi-Speaker TTS is the one that makes you feel like you're cheating: it synthesizes a full conversation between up to ten cloned voices in one pass - two people bantering, a news anchors panel, a fake podcast interview - without you splicing audio or queueing ten separate generations.
You connect a reference clip for each participant, write the dialogue with [speaker_1]:-style markers, and the node returns one continuous audio file where the voices trade lines naturally. It builds on Fish S2 Pro's zero-shot cloning, so the "voices" are whoever you feed in - a couple of 10-second samples each and you've got your cast.
How it actually works
Worth knowing, because it sets expectations: the node doesn't generate the whole conversation in one autoregressive sweep. It parses your script into individual turns, generates each line separately using that speaker's reference audio (seeded seed + line_index so each line varies a bit), then concatenates the results with pause_after_speaker seconds of silence between turns - 0.4s by default, which reads as natural pacing for most dialogue. That's also why the node requires every speaker to have a reference clip connected: it'll throw a clear Reference audio required for all speakers error if one's missing.
You don't need to hunt the model's native <|speaker:0|> syntax either - the node converts your friendly [speaker_1]: text into the model format for you.
Inputs that matter
- num_speakers - 2 to 10. This is the fun part: it's a dynamic input. Change it and the node shows or hides exactly that many
speaker_N_audioandspeaker_N_ref_textfields on the panel. No fishing for the right dropdown. - speaker_N_audio - the reference clip for each person (5–30s each).
- speaker_N_ref_text - optional transcript per speaker; recommended for stability, same reasoning as the voice-clone node.
- text - the script, one line per turn:
Inline[speaker_1]: Hello, I'm speaker one. [speaker_2]: And I'm speaker two![laugh]/[whisper]tags still work per line. - pause_after_speaker - seconds of silence between turns (0–2). 0.4 is a good default; nudge it up for a more ponderous back-and-forth, down for rapid-fire comedy.
Everything else (model_path, language, precision, attention, temperature) is shared with the base Fish S2 TTS node, and the same guidance applies - leave them alone until you know why you're changing them.
Output is a single audio (AUDIO) track, ready for SaveAudio or a lip-sync model.
Install and gotchas
Same pack, same story: ComfyUI Manager → search "FishAudioS2" → install → restart, or clone https://github.com/Saganaki22/ComfyUI-FishAudioS2.git into custom_nodes/. Deps auto-install on startup; models auto-download to ComfyUI/models/fishaudioS2/ on first use. Watch the shared pack traps: don't pip install fish-speech (bundled, and it'll downgrade PyTorch), restart once if nodes fail to load, and use the BNB NF4/INT8 model options to squeeze this onto a 16GB card.
Two things that bite specifically on this node: the dynamic num_speakers inputs need a recent-ish ComfyUI (there's a legacy fallback if yours is old, but the dynamic version is much nicer), and every speaker must have a reference connected or the run fails on the first missing one. Also remember the Fish Audio Research license - non-commercial. Free for your projects, not for a product.
The one honest caveat: per-line generation means there's no cross-speaker prosody modeling - characters don't interrupt each other or talk over one another. For scripted, turn-based dialogue it's great and way faster than building it by hand. If you need genuine back-and-forth interruptions, that's a different (and heavier) problem entirely.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| model_path | COMBO | S2-Pro checkpoint folder name. Place model folders in ComfyUI/models/fishaudioS2/ | |
| text | STRING | [speaker_1]: Hello, I'm speaker one. [speaker_2]: And I'm speaker two! | Multi-speaker text. Use [speaker_1]:, [speaker_2]:, ... to assign lines to each connected speaker. Supports inline tags: [laugh], [whisper], etc. |
| language | COMBO | Language hint. 'auto' lets the model detect it. | |
| device | COMBO | Compute device. 'auto' picks CUDA > MPS > CPU. | |
| precision | COMBO | Model precision. 'auto' picks bfloat16 for full model, float16 for quantized model. bfloat16 recommended for CUDA. | |
| attention | COMBO | Attention kernel. 'auto' uses model default. 'sdpa' forces PyTorch SDPA. 'flash_attention' forces FlashAttention. 'sage_attention' requires sageattention package. BNB models (s2-pro-bnb-int8/nf4) always use sdpa regardless of this setting. Changing this reloads the model. | |
| max_new_tokens | INT | 00–4096 | Max acoustic tokens. 0 = auto. |
| chunk_length | INT | 200100–400 | Chunk length for iterative synthesis (100-400). |
| temperature | FLOAT | 0.800.1–1 | Sampling temperature. |
| top_p | FLOAT | 0.800.1–1 | Top-p nucleus sampling cutoff. |
| repetition_penalty | FLOAT | 1.100.9–2 | Repetition penalty. Higher = less repetition. |
| seed | INT | 00–2147483647 | Random seed. |
| keep_model_loaded | BOOLEAN | true | ON = model stays in VRAM between runs. OFF = unloaded after each run. |
| offload_to_cpu | BOOLEAN | false | After generation, move the model to CPU instead of keeping it in VRAM. Frees VRAM while avoiding the full reload penalty. Ignored if keep_model_loaded is OFF. |
| compile_model | BOOLEAN | false | torch.compile for ~10x speedup after warmup. Not supported on Windows. |
| pause_after_speaker | FLOAT | 0.40–2 | Seconds of silence to add after each speaker turn. |
| num_speakers | COMBO | How many speakers (2-10). Changing this shows/hides speaker audio inputs. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |