You have an adult script, whether a voice message, a fiction chapter or a two-character scene, and you want it spoken as written, with the breaths and sighs, and you want to know what it will cost. Gemini 2.5 Pro TTS does that on SpicyAPI. SpicyAPI adds no content filter: in our September 2026 tests, adult scripts came back as complete audio, with nothing skipped, softened or cut short.
What to do now, in the Playground:
- Pick a Voice for the mood:
Enceladus(breathy),Achernar(soft),Sulafat(warm),Gacrux(mature) or the defaultKore(firm). - Set Style (
Whisperis the usual choice for intimate material), then add one or two sentences in Delivery instructions or Scene for the moment. - Put sounds in square brackets inside Text, such as
[sighs]or[laughs]. These cues were performed as sounds in our examples; if one is spoken, move its direction into Delivery instructions. - For two characters, use Dialogue and Speakers instead of Text.
Try it in the Playground first
Open Gemini 2.5 Pro TTS and use the Playground tab with the Form view:
- Paste your script into Text (up to 5,000 characters). The Cues shortcuts insert
[whispers],[sighs],[laughs],[gasps]and[pause]. - Pick a Voice (for example
Enceladus · Breathy), then set Style toWhisperand Pace toUnhurriedfor the slow, lingering reading. - Write one or two sentences in Delivery instructions and Scene. Neither is spoken.
- Check the length-based estimate under Text, press Run model, and play the result in Output. Download the WAV from there.
Audition your hardest passage here before you write any code: a cue that is spoken instead of performed in the Playground will be spoken from the API too. The settings below explain each control.
Settings that change the result
voice_id takes one of 30 prebuilt voices. The default is Kore.
| Mood | Voices to audition |
|---|---|
| Breathy, close | Enceladus |
| Soft, gentle | Achernar, Vindemiatrix |
| Warm | Sulafat |
| Mature, gravelly | Gacrux, Algenib |
| Firm | Kore, Orus |
| Upbeat, breezy | Puck, Aoede |
Four optional fields then shape the performance. None is read aloud.
stylesets the overall manner:whisper,empathetic,vocal_smile,newscaster,promo_hypeordeadpan.pacesets the rhythm:natural,rapid_fire(fast, clipped),the_drift(slow, lingering) orstaccato(short, separated phrases). Slower pacing means more seconds of audio, and seconds are what you pay for.instructions(up to 1,000 characters) is free text on mood, distance from the microphone and who is being addressed. One or two sentences work better than a list of adjectives: "close to the microphone, unhurried, as if speaking only to the listener".scene(up to 500 characters) says where and to whom the words are spoken, such as "a quiet hotel room after midnight".
accent (eight English accents, English scripts only) and temperature (how much takes differ) are optional; leave them unset until you want a variation. There is no language field; the model detects the script's language and each voice keeps its character.
Write the script so it performs
Inside text, short bracketed cues mark where to perform a sound or delivery change. [sighs] and [laughs] were performed in our examples. Use style: "whisper" or instructions for a longer passage's delivery; if a tag is spoken as a word, use those fields instead. Ellipses suggest pauses.
Two habits help:
- Write for the ear. Spell out what should be said, use ellipses and commas for pauses, and keep sentences short.
- Direct in the fields, not in the text. If you write "she whispers breathlessly" inside
text, it will be read as words. Put that instyleorinstructions.
Then call it from code
This block creates the task, waits for it and prints the WAV link (pip install spicyapi, with SPICY_API_KEY set):
import uuid
from spicyapi import SpicyClient, output_assets
client = SpicyClient() # reads SPICY_API_KEY from the environment
task = client.create_task(
model="google/gemini-2.5-pro-tts/text-to-speech",
input_data={
"text": "Hey... it is me. [sighs] I know it is late. Stay on the line a little longer?",
"voice_id": "Enceladus",
"style": "whisper",
"pace": "the_drift",
"scene": "A quiet bedroom after midnight, speaking to one listener",
"instructions": "Close to the microphone, unhurried, a little tired.",
},
idempotency_key=str(uuid.uuid4()), # new key per new request; reuse only to retry the same one
)
final = client.wait_for_terminal(task["taskId"])
if final["state"] != "succeeded":
raise RuntimeError(f"Task {task['taskId']} ended as {final['state']}")
print(output_assets(final)[0]["url"]) # a 24 kHz, 16-bit mono WAV; copy it to your own storageThe audio is kept for 14 days and there are no word timings or subtitles. Waiting, retries, expiring result links and error handling are in the Python SDK reference, the task documentation and retention.
Or let an Agent run it
If an assistant should generate the voice notes, give it the CLI or the MCP server; both show the price and ask you to confirm before a paid call. The Skill adds instructions on top of either.
- CLI.
spicyapi(npx @spicyapi/cliworks without installing);input.jsonholds theinputobject from the block above:
``bash spicyapi tasks create --model google/gemini-2.5-pro-tts/text-to-speech \ --input-file input.json --wait ``
- MCP server. Add the MCP server, then ask: "Read this script in a whispered Enceladus voice with Gemini 2.5 Pro TTS." It calls
spicyapi_task_create(which stops for your price confirmation) andspicyapi_task_wait. - Skill.
npx skills add spicyapi-ai/spicy-skillinstalls the Agent Skill, which teaches a coding assistant to read the live schema and reuse idempotency keys. It cannot run tasks by itself, so use it with the CLI or MCP.
Two characters in one clip
For a scene between two characters, send dialogue instead of text (not both), plus speakers with the cast. Each speaker has a name that the lines refer to and a voice_id, and can set its own accent, style and pace, plus a short profile describing who is speaking (not read aloud). Anything a speaker leaves out falls back to the top-level values. Each dialogue line is {speaker, text}, performed in order, with up to 20 lines of 250 characters each and a maximum of two speakers. Same call as above: replace the input object with this one.
{
"speakers": [
{ "name": "Mara", "voice_id": "Sulafat", "style": "whisper", "profile": "Warm, close, unhurried" },
{ "name": "Jonah", "voice_id": "Charon", "profile": "Low, amused" }
],
"dialogue": [
{ "speaker": "Mara", "text": "Stay a little longer." },
{ "speaker": "Jonah", "text": "[laughs] You say that every time." },
{ "speaker": "Mara", "text": "And every time you do." }
],
"scene": "A quiet apartment after midnight"
}The conversation comes back as one mixed WAV. To edit one character's lines on their own later, generate each character as a separate single-voice task and join the files in your editor. For longer scenes, more than two voices, or a voice cloned from a reference clip, see the TTS comparison and the Chatterbox voice reference guide.
What it costs
Billing is per second of audio actually returned, measured from the file, at $0.00045 per second. Length depends on voice, style and pace: a 270-character paragraph runs 23 to 29 seconds, so cost is roughly character count divided by 10, times $0.00045.
| Clip length | Cost | Roughly how much text |
|---|---|---|
| 15 seconds | $0.0068 | 150 characters |
| 30 seconds | $0.0135 | 300 characters |
| 60 seconds | $0.027 | 600 characters |
| 5 minutes | $0.135 | 3,000 characters |
| 7 to 9 minutes | $0.19 to $0.24 | 5,000 characters, the limit for text |
While a task runs, a hold of about $0.30 (660 seconds at the per-second rate, covering the longest clip the model can produce, about 655 seconds) is placed on your balance, and the unused part is released when the audio is measured. A failed request is not charged. Keep at least that much balance free before you queue a batch, since holds on earlier tasks can crowd out the next one.
Where it trips people up
- A cue is read as a word. Reword it, or move the direction into
styleorinstructionsand keep only the sound in brackets. - Direction seems ignored.
accentonly affects English scripts;styleandpaceset at top level apply to every speaker that does not set its own. - You sent both
textanddialogue. Pick one;dialoguealso requiresspeakers.
When to use a newer Gemini voice instead
Gemini 3.8 Flash TTS ($0.00032 per second) and Gemini 3.8 Flash-Lite TTS ($0.00021 per second) take the same fields, including dialogue, at a lower price. Flash-Lite tends to read some bracketed cues aloud, so choose Pro when the breaths and sighs matter. Flash usually performs bracketed cues too; audition a short passage first. The Gemini 3.8 narration guide covers those two in detail.
FAQ
Is Gemini 2.5 Pro TTS uncensored?
Our tested adult scripts came back complete, without words skipped or softened. SpicyAPI adds no extra content filter. You stay responsible for the scripts and for how you use the audio, including not presenting it as a real person's words. Keep characters fictional and adult.
Are cues like [sighs] or [laughs] read out loud?
The tested [sighs] and [laughs] examples performed them as sounds. If another cue is spoken, move that direction into instructions or use style. Other models differ, as the TTS comparison above explains.
What is the difference between instructions, scene and style?
style is a fixed list of overall manners. instructions is free-text direction on delivery, and scene says where and to whom the words are spoken. Use style first, then add instructions or scene for the moment.
How much does a minute of audio cost?
About $0.027, billed on the seconds returned rather than on script length.
Can I clone a voice?
Not on this endpoint. Pick from the 30 prebuilt voices, or use a model that takes a reference clip.
Start in the Playground (create an account first): Enceladus, Whisper, and a short script with one [sighs] cue show how the direction lands.





