Gemini TTS
2,000 voices, one text box, and a typo that costs you a run
- audio
Audio in ComfyUI has always been the awkward layer. The models are good, the integration is a permanent workaround - you're forever one pip install away from a transformers fight that takes three other packs down with it. So if your workflow ends in a Wan S2V or an LTX render and you just need a voice to feed it, calling Google's speech model from inside the graph is the boring, reliable answer. Transcript in, AUDIO tensor out, right type for SaveAudio or whatever lip-sync node comes next.
GeminiTTS3Node is the current Gemini TTS node in ComfyUI-ExternalAPI-Helpers. It ships next to an older Gemini TTS (Legacy) in the same pack, and that's the first thing to get straight, because half the tutorials out there were written against the legacy node. If a guide tells you to pick Zephyr from a dropdown and set pace and accent, it's describing that one - this node has no such dropdowns.
Where the voices come from
The hook is the voice library. The author's README pitches Google's "Extended Voice Library" - 2,000-plus voices, the kind of names that show up as Bodi, Lumi, Koda, Nika, Tavi - and the legacy celestial set (Puck, Zephyr) still works too. ElevenLabs is still the reliability bar; this is the hosted option that doesn't feel like a downgrade.
The catch is how you pick one: voice is a plain text field, not a dropdown. Autocomplete won't catch a typo, so a misspelled voice doesn't fail in the UI - it fails when the request hits Google and comes back as a Gemini API Error. Copy names out of AI Studio, not off a screenshot.
How it works
The mechanism is straightforward. It builds a google-genai client from your key and streams the response (generate_content_stream), accumulating audio bytes chunk by chunk instead of waiting on one blob.
- Your text gets wrapped. Unless it already starts with
## Transcript:, the node prepends that header before sending. Don't hand-write your own transcript-style markdown - you're just fighting the wrapper the model expects. - That format is what makes the inline tags work. The
texttooltip lists the full set the author supports:<breath>,<laugh>,<sigh>,<long pause>,<whispering>,<cough>, and thirty-odd more. They're point-in-time - a breath lands where you typed it - which is the whole reason this is more fun than a straight read-through.
Audio comes back as raw PCM or a RIFF WAV container; the node decodes it to float32 and returns {"waveform", "sample_rate"}, standard ComfyUI AUDIO. One quirk: IS_CHANGED hashes your inputs, so re-queueing the same graph won't call the API again. Great for your wallet, confusing the first time you hit Queue expecting a different take. Change seed for a new one.
Inputs that matter
text- the transcript, inline tags and all. Empty raises immediately.voice- as above, free text, defaultBodi.style- the optional acting note, passed through tospeech_metadata. The author's example: "Bright, sunny morning greeting with a subtle vocal smile and crisp pacing." Add theStyle:prefix yourself or the node does it for you. This is your global direction; the inline tags are the local ones.model-gemini-3.8-flash-tts(default) orgemini-3.8-flash-lite-tts.api_key- a raw key or the name of an env var.temperatureandseedare the variation levers; leave them near default until you have a reason.
Install
ComfyUI Manager, search ExternalAPI-Helpers, or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/Aryan185/ComfyUI-ExternalAPI-Helpers.git
cd ComfyUI-ExternalAPI-Helpers
pip install -r requirements.txt
Restart ComfyUI. Then put your key in a .env next to the pack's files - GEMINI_API_KEY=... - and set api_key to GEMINI_API_KEY instead of pasting the raw key into the widget. Workflow JSONs get shared freely, and a key baked into a widget travels with them. Free key over at AI Studio.
Where people get burned
Don't skip requirements.txt. This node alone needs only google-genai and torch, but the pack's __init__.py imports every module in the pack on load, with no per-module guard. One missing dependency - av and opencv-python are in there for the video and image nodes - takes the whole pack down, and it fails as "no Gemini TTS node in the menu," not as anything naming the real culprit.
Long scripts need chunking. True of TTS in this ecosystem generally, not just here: past a couple of minutes of narration, people cut the transcript into beats and stitch the audio afterward. Long speech either crashes or gets worse.
Your key and text leave the machine. This is an API node - the category that already shipped credential-stealing malware once under a friendly "vision node" name. Verify this pack rather than assuming.
If you get Gemini API Error, the raw API message is in the traceback - usually a bad voice name or exhausted quota. If you get "contained no audio data," the request went through and came back without speech; reword and re-run rather than assuming the node broke.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | Transcript text. Supports inline tags: <argh>, <breath>, <cackle>, <cheer>, <chuckle>, <chuckles>, <cough>, <cry>, <exhales>, <gasp>, <giggle>, <groan>, <growl>, <grr>, <grunt>, <heavy breath>, <hiss>, <laugh>, <laughter>, <long pause>, <moan>, <pant>, <pff>, <phew>, <scream>, <short pause>, <shout>, <shriek>, <sigh>, <sighs>, <sneeze>, <snicker>, <snort>, <sob>, <throat-clearing>, <tsk>, <whimper>, <whispering>, <whispers>, <yawn> | |
| voice | STRING | Bodi | Voice name from AI Studio (e.g. Bodi, Lumi, Sola, Koda, Nika, Tavi, Kira, Ludo, or legacy celestial names like Puck, Zephyr) |
| model | COMBO | gemini-3.8-flash-tts | 2 options: gemini-3.8-flash-tts, gemini-3.8-flash-lite-tts |
| api_key | STRING | Directly put Gemini API key or .env variable name (GEMINI_API_KEY) | |
| seed | INT | 69-1–2147483646 | — |
| temperature | FLOAT | 1.000–2 | — |
| styleopt | STRING | Acting style passed to speech_metadata (e.g. 'Bright, sunny morning greeting with a subtle vocal smile and crisp pacing.') |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |