Gemini 3.8 Flash TTS · Text to Speech
The middle Gemini voice, and the one I'd actually pick
- audio
- task id
Why this one
Three Gemini speech nodes, three prices: Flash-Lite at 0.03 credits a second, this at 0.05, 2.5 Pro at 0.07. Flash sits in the middle and hits the sweet spot - it acts out the direction cues, which is the entire reason to use a Gemini TTS rather than a plain reader, without the Pro node's slower turnaround and higher rate.
Concretely: put [whispering] or [sighs] in text and the model performs it. That's the author's own note on the field, and it's the difference between a voice reading a script and a voice acting one. If you're building the audio bed of a video in the same graph that generates the shots, this is the node to reach for.
What happens when you queue
The text (or a scripted two-person dialogue) goes to PopNow, gets quoted, is submitted with an idempotency key, and the node polls until the take is ready. Then it downloads and decodes the audio to the AUDIO dict every ComfyUI audio node understands. Multiple takes come back as a batch, resampled and padded to a common length, so Save Audio drops one file per take.
No weights, no VRAM, no dependency stack - this pack installs nothing (dependencies = [] in its pyproject.toml) and leans on aiohttp, torch and Pillow that ComfyUI already has. Whether that's a win depends on what you're comparing against: against local Chatterbox, you're trading privacy and a filter for zero setup and no VRAM fight.
The fields
Two ways to feed it. text for a single voice, exactly as written, with bracketed direction inline. Or dialogue - a JSON list of {"text", "speaker"} objects - plus speakers, a JSON list of one or two voices, each with a name the lines point at, a required voice_id, and optional pace, style, accent, profile. Leave those two empty for narration; they're used instead of text.
The voice and its manner. voice_id is a combo, default Kore, one fixed character per option. style and pace both default to model default, meaning the field is dropped from the request and the voice keeps its own habits. accent also defaults to model default on this node.
Direction that isn't spoken. instructions describes how to read - mood, distance from the mic, who's listening. scene describes where and to whom. Neither reaches the listener as words, both change the performance. This pair is the underrated part of the node; a flat line often fixes itself with three words in instructions.
temperature - -1 to 2, step 0.05, default -1 (model's choice). Push it up when you want takes that differ; keep it low when you need a line reproduced.
Outputs: audio (AUDIO) and task id (STRING).
Install
comfy node install popnow-comfyui
# or
cd ComfyUI/custom_nodes && git clone https://github.com/popnow-ai/popnow-comfyui
Restart, add a key from popnow.ai/api/console/keys in Settings > PopNow (or export POPNOW_API_KEY), restart again so the catalog loads from your account. If you used the old single-file popnow_api.py, delete it before you start.
Getting unstuck
PopNow 401 and No PopNow API key is set are key problems, full stop. 400 naming a field means that field's value isn't acceptable - with dialogue and speakers that's usually broken JSON, since both are plain string widgets that just happen to want JSON inside. 40201 is an empty wallet; at 0.05 credits a second, a two-minute VO is about six credits. 40004 means the setting combination can't be served. 40310 wants your email verified. Declined generations return as content_rejected and cost nothing.
The thing nobody expects: cancelling doesn't cancel. The task keeps running on PopNow, gets charged if it succeeds, and the result turns up in your API console logs later.
One more caution, and it's about the pack rather than the model: PopNow has essentially no community footprint yet - no threads, no war stories, no one to tell you where the rough edges are. The code is MIT and readable, but you're an early user. Keep the key in the environment so it never lands in a shared workflow, and don't route production audio through it until you've run it enough to trust it.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | Words to speak, up to 10,000 characters. Native inline cues include <laugh>, <sigh> and <short pause>. | |
| dialogue | STRING | A scripted conversation, used instead of text: each line names a speaker from speakers. JSON. A list of objects with "text", "style"?, "speaker". | |
| speakers | STRING | The cast for dialogue: one or two voices, each with a name the lines refer to. JSON. A list of objects with "name", "pace"?, "style"?, "accent"?, "profile"?, "voice_id"?, "consent_audio_url"?, "reference_audio_url"?. | |
| voice_id | COMBO | Kore | Prebuilt voice that reads the text. Each voice has a fixed character. |
| style | COMBO | model default | Overall manner of the reading. Omit it to use the voice's own default manner. |
| pace | COMBO | model default | Rhythm of the reading. Omit it to keep the voice's own rhythm. |
| accent | COMBO | model default | English accent used for the reading. |
| instructions | STRING | How to read the text: mood, distance from the microphone, who is listening. Shapes the delivery and is not spoken. | |
| scene | STRING | Where and to whom the words are spoken. Shapes the delivery and is not spoken. | |
| filler_words | BOOLEAN | false | Allow filler words in a two-speaker conversation. Has no effect on single-speaker requests. |
| temperature | FLOAT | -1.00-1–2 | Variation between takes; higher is less predictable. -1 leaves it to the model. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | Several results come back as a batch; Save Audio writes one file each. |
| task id | STRING | The PopNow task id, for the API console logs or support. |