Models

Text to speech API: generate speech in an avatar's voice

Sume's text to speech API, POST /v1/tts-1.0/generate, speaks up to 20,000 characters in a ready avatar's voice, with word timestamps and sentence audio slices.

5 min readSume
All posts

To convert text to speech with the Sume API, send POST /v1/tts-1.0/generate with a transcript of up to 20,000 characters and a voice: the avatar_id or avatar_handle of an avatar whose voice is ready, or a voice.id. TTS 1.0 runs as a job and returns the audio as a Sume-hosted file, with optional word timestamps and per-sentence clips.

Details come from the TTS request schemas in the Sume API reference, the OpenAPI document behind the API reference docs, read on 2026-09-26. The price is read from the code behind API pricing. For a finished talking video from a script, use the talking avatar video API instead.

How do I choose the voice?

The discoverable voice is an avatar's. GET /v1/avatar-1.0/avatars lists your avatars, and each summary carries voice.status: processing, ready, or failed (voice is null for an avatar with no voice). Pass a ready avatar's avatar_id or avatar_handle at the top level of the body, not inside voice, and Sume resolves that avatar's voice at submit time. How to create a reusable AI avatar covers making one.

If you already hold a Sume voice id, send it as voice.id: a voice UUID or a Voices library id (voi_ plus 32 hex characters). Any other shape fails with 400 and invalid_voice_id before a job is queued or credits are reserved. If you send an avatar and voice.id together, they must match, or the request fails with 400.

What does a text to speech request look like?

This request speaks one line in a ready avatar's voice as a 44,100 Hz pcm_s16le wav, with word timings and one audio slice per sentence:

curl -X POST https://api.sume.com/v1/tts-1.0/generate \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: tts-welcome-001" \
  -d '{
    "transcript": "Welcome back. Today we test the new travel mug.",
    "avatar_handle": "product_host",
    "language": "en",
    "output_format": { "container": "wav", "encoding": "pcm_s16le", "sample_rate": 44100 },
    "timestamps": { "words": true },
    "segmentation": { "mode": "sentence" }
  }'

Which fields shape the audio?

transcript plus one voice selector is the minimum. Everything else is optional.

From the TTS 1.0 request schema in the Sume API reference, read 2026-09-26.
FieldWhat it takes
transcript1–20,000 characters. Spaces and punctuation count toward usage.
languageA BCP-47 / ISO-639 code such as ko, ja, or en.
output_format.containermp3 (default), wav, or raw.
output_format.sample_rate8000, 16000, 22050, 24000, 44100 (default), or 48000 Hz.
output_format.bit_rateFor mp3: 32000, 64000, 96000, 128000 (default), or 192000. Required for mp3 when you override the defaults.
output_format.encodingFor wav or raw: pcm_f32le, pcm_s16le, pcm_mulaw, or pcm_alaw.
generation_configvolume 0.5–2.0, speed 0.6–1.5, and an optional emotion guide.
pronunciation_dict_idAn optional pronunciation dictionary id.
modeasync (default), sync, subscribe, or webhook.

How do I get word timestamps and per-sentence audio?

Two options turn one synthesis into timed pieces you can caption or cut. A sentence clip on the Sume media host is also the typical audio_url for lip sync on a still image.

  • timestamps: { "words": true } adds words[] to the completed job result: monotonic word timings with start and end in seconds.
  • segmentation: { "mode": "sentence" } requires timestamps.words: true and returns gapless segments[], each ending exactly where the next begins. sentence is the only mode in v1.
  • boundary_lead_ms (0–500, default 70) places the cut that many milliseconds after a sentence's last word; the next segment absorbs the pause.
  • With emit_audio (default true) and a wav or raw container, each segment carries a sample-exact audio_url. With mp3 you get the timings without per-segment audio.

When should I use the TTS Router instead?

TTS 1.0 has no engine picker, and a model or model_id in its body is rejected with 400. To choose the engine, call POST /v1/tts-router/generate with a required model: sonic-3.6, sonic-3.5, sonic-3, sonic-latest, sonic-preview. Voice selection, transcript rules, and billing match TTS 1.0. job.model echoes the id you sent, and an unknown id fails with 400 model_not_found.

GET /v1/tts-router/models lists those ids with each model's capabilities (text_to_speech, max_characters), pricing, and constraints. The sonic-preview entry's constraints mark it as the provider's beta channel, whose output and availability can change without notice. GET /v1/tts-router/models/{model_id} returns one model, or 404 for an id it does not know.

What are the limits, and what does it cost?

TTS 1.0 costs $0.0475 per 1,000 characters, plus a 5.5% agent fee by default, and the TTS Router bills the same way. Usage is priced per transcript character, spaces and punctuation included, so a full 20,000-character transcript comes to $0.95 before the fee.

  • Synthesized audio longer than 1,200 seconds fails with tts_duration_exceeded, and no credits are captured.
  • Set language for every non-English transcript. Omitted, it defaults to English, with Korean or Japanese inferred from a Hangul- or kana-only transcript as a fallback.
  • The route is non-streaming. sync and subscribe block for at most 30 seconds, and /result returns 409 job_not_completed until result_ready is true.
  • The top-level speed enum (slow, normal, fast) is deprecated; use generation_config.speed.

Sources

Related posts

Written by Sume