Gemini 2.5 Pro TTS · Text to Speech
Narration and two-hander dialogue, from a node
- audio
- task id
Speech that gets stage directions
Local TTS in ComfyUI is a maintained workaround - the models are good, but the integration layer is a permanent fight with torch and tokenizer versions, which is exactly why the TTS Audio Suite had to move to per-engine isolation. This node skips all of that by not being local at all. It calls Google's Gemini 2.5 Pro TTS and hands you back a normal AUDIO object.
What makes it more than a novelty is the directing. Most TTS gives you a voice and a text box. This one separates what is said (text) from how it's said (instructions), from where it's said (scene), and lets you script a two-person exchange without a second node. It's priced per second of output - 0.07 credits - which makes a 30-second narration cheap and a ten-minute audiobook chapter less so.
How it works
Your text goes to PopNow, gets quoted, is submitted as a task, and the node polls it until the audio is ready, then downloads the file and decodes it to the standard ComfyUI audio dict. Several results come back as a batch - the node pads them to the longest clip and matches sample rates, so a node like Save Audio writes one file per take. Downstream audio tools see one waveform stack, not a mess.
The pack itself has no dependencies beyond what ComfyUI ships. There's no model to load, no VRAM cost, and nothing to quantize - the trade is that everything you type goes to a vendor's server.
The fields, grouped honestly
The text. text is the words, exactly as written, and cues in square brackets like [sighs] are performed rather than read out. That's the feature that sells the model. For two speakers, leave text empty and fill dialogue - a JSON list of objects with "text" and "speaker" - plus speakers, a JSON list of one or two voices, each with a name the dialogue lines refer to, a required voice_id, and optional pace, style, accent and profile.
The voice. voice_id is a combo defaulting to Kore; each prebuilt voice has a fixed character, so picking one is picking a person. style and pace both default to model default, which genuinely means the field is omitted and the voice behaves as it naturally does - a real default, not a placeholder.
The direction. instructions is how to read it - mood, pace, distance from the mic, who's listening. scene is where and to whom. Neither is spoken aloud. This is where the model earns its keep: "as if explaining something obvious for the third time" in instructions does more than any punctuation trick.
The dial. temperature runs -1 to 2 in steps of 0.05, and -1 means "let the model decide". Raise it for varied takes; leave it alone until you have a reason.
Outputs
audio (AUDIO) - batch, one entry per returned take - and task id (STRING), which is what you paste into a support request or search for in the API console.
Install
comfy node install popnow-comfyui
or ComfyUI Manager → search PopNow → Install. Restart, paste a key from popnow.ai/api/console/keys into Settings > PopNow (or set POPNOW_API_KEY), restart again. The second restart matters - the node list comes from your account's catalog at startup.
Practical trouble
Empty text with empty dialogue gets you a rejected request, since speech models take one or the other; the tooltip's phrase "used instead of text" is literal. A PopNow 400 naming dialogue or speakers almost always means malformed JSON - a missing quote, or curly quotes pasted in from a doc. 40201 means the wallet ran dry, and at 0.07 credits a second, long scripts burn faster than you'd guess: a five-minute narration is roughly 21 credits. content_rejected comes back refunded.
One behaviour to internalise: cancel stops your wait, not the job. The generation continues on PopNow and is charged if it succeeds.
And since it's a young vendor pack with no community track record to lean on, keep the key in the environment rather than a workflow, and don't build a paid pipeline around a node you haven't run a dozen times.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | The words to be spoken, exactly as written. Cues in square brackets such as [sighs] are performed rather than read aloud. | |
| dialogue | STRING | A scripted conversation, used instead of text: each line names a speaker from speakers. JSON. A list of objects with "text", "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". | |
| 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 | neutral | English accent used for the reading. |
| instructions | STRING | How to read the text: pace, 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. | |
| 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. |