Skip to navigation

Stream Speech (SSE)

View as Markdown

Synthesize speech and stream the audio back over Server-Sent Events. Same body as /waves/v1/tts — the only difference is the response is a stream of base64-encoded PCM chunks instead of one binary blob.

Pick the model with the model body parameter, same as the sync route.

The same URL serves the WebSocket endpoint. wss://api.smallest.ai/waves/v1/tts/live accepts a WebSocket upgrade for streaming-text scenarios (LLM token streams, live captioning). The HTTP POST documented on this page returns SSE; use wss:// to use the WebSocket protocol instead. See the WebSocket reference.

When to use this

  • Use this when you want playback to start before synthesis is complete — long passages, latency-sensitive UI, live narration.
  • Use sync /waves/v1/tts when total latency doesn’t matter and you’d rather get one buffer.
  • Use /waves/v1/tts/live (WebSocket) when the text arrives incrementally (LLM token stream). SSE assumes you have the full text up front.

How it works

  1. POST your text + voice settings — same payload as /waves/v1/tts, plus optional model.
  2. The response is Content-Type: text/event-stream. Each chunk frame is event: audio\n followed by data: {"audio": "<base64-pcm>", "done": false, "status": "206"}\n\n.
  3. Decode each chunk’s audio field with base64 and feed the PCM bytes to your audio pipeline (browser MediaSource, ffmpeg pipe, raw PCM player, etc.).
  4. A final data: {"status": "200", "done": true}\n\n frame marks end of stream. Detect the terminator with done == true; every chunk frame also carries done: false, so "done" in msg matches every frame.

Examples

cURL

curl -N -X POST "https://api.smallest.ai/waves/v1/tts/live" \
-H "Authorization: Bearer $SMALLEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Streaming this paragraph chunk by chunk so playback can start sooner.",
"voice_id": "magnus",
"sample_rate": 24000,
"output_format": "pcm"
}'

Common gotchas

  • Use a streaming-friendly client. curl -N, Python iter_lines, or a fetch ReadableStream reader. Buffering clients will hide the latency win.
  • Audio is base64 inside the event payload, not the raw event bytes. Decode the data.audio field per event.
  • output_format=pcm gives the lowest overhead for streaming playback. wav/mp3 work but add per-chunk framing bytes.

Authentication

AuthorizationBearer

API key authentication. Include your key as Authorization: Bearer YOUR_API_KEY. Access tokens are not accepted on this endpoint.

Headers

x-expire-contentenumOptional

Enterprise plans only. Set to true to expire this request’s content. The input text is deleted within 7 days; the usage record (credits, character count, model, latency) is kept. Omit the header to keep content. On other plans the header is ignored and the request is processed normally. See Zero Data Retention.

Allowed values:

Request

This endpoint expects an object.
textstringRequired1-8000 charactersDefaults to Hello from Waves TTS.

The text to convert to speech. Max 8000 characters after trim; whitespace-only strings are rejected.

voice_idstringRequiredDefaults to magnus
The voice identifier to use for speech generation. See the model card for available voices per model.
modelenumOptionalDefaults to lightning_v3.1

TTS model to route the request to. Controls which model pool serves this synthesis.

  • lightning_v3.1 (default) — standard Lightning v3.1.
  • lightning_v3.1_pro — Lightning v3.1 Pro pool. Improved audio quality and naturalness, with a curated voice catalog. See the Lightning v3.1 Pro model card for supported voice IDs.

Same concurrency and latency profile across both. Other request parameters behave identically.

Allowed values:
sample_rateenumOptionalDefaults to 44100
The sample rate for the generated audio.
Allowed values:
speeddoubleOptional0.5-2Defaults to 1
The speed of the generated speech.
languageenumOptional

Language code for synthesis. Influences pronunciation, number/date normalization, and phoneme selection.

Default on lightning_v3.1_pro: when language is omitted, the Pro pool defaults to en + hi (mixed Indian + Western English coverage, auto-detected from the input text).

Each voice has its own tags.language set in the voice catalog — query GET /waves/v1/lightning-v3.1/get_voices. Pass a language the voice was trained on; passing other codes is accepted by the API but produces English-pronounced output.

auto (recommended for cross-language use cases): routes internally based on the input text. Any English or Hindi voice can be used across all supported languages when auto is set; the platform handles language-appropriate routing without needing a code per call.

On lightning_v3.1 — 20 supported languages:

  • 10 European: English, Spanish, French, German, Italian, Dutch, Swedish, Portuguese, Polish, Russian
  • 10 Indic: Hindi, Marathi, Gujarati, Punjabi, Bengali, Odia, Tamil, Telugu, Kannada, Malayalam

On lightning_v3.1_pro — 31 supported languages (adds 11 over base):

  • 13 European: base 10 plus Greek, Finnish, Norwegian
  • 8 Asian & Middle Eastern: Chinese, Japanese, Korean, Indonesian, Malay, Vietnamese, Turkish, Arabic
  • 10 Indic: same as base
  • Pass en → UK + American accented English.
  • Pass hi → Indian accented English + Hindi (code-switching).
  • Omit language → defaults to en + hi (mixed Indian + Western English coverage, auto-detected from input text).
number_pronunciation_languageenumOptional

Optional. Sets the language used to read out numeric content — numbers, currency amounts, times, and the numeric parts of dates and years — independently of the synthesis voice. Ordinary words are not translated.

  • If you omit language, this value also becomes the synthesis language: model selection and voice routing follow it.
  • If you set language explicitly, language always wins for synthesis and number_pronunciation_language only changes how numeric content is normalized. It works both ways — read numbers in Hindi under an English voice, or in English under a Hindi voice (tuned for Indian, often mixed-script, use cases).
  • Omit this field to keep the existing behaviour — normalization follows language.

Note: only numeric tokens are re-spoken; the words around them stay in the text language. On a cross-language request names may also render in the target script (e.g. “Smith” → “स्मिथ”), which is generally the desired reading for native-language voices.

Accepts the same language codes as language (including auto, nl, sv).

date_formatenumOptional

Optional. Controls how all-numeric dates (e.g. 05/03/2024) are read out, independent of the synthesis voice:

  • EU — day/month order (DD/MM): 05/03/2024 → “fifth March, twenty twenty four”.
  • US — month/day order (MM/DD): 05/03/2024 → “May third, twenty twenty four”.

Omit this field to keep the existing behaviour: English dates default to US (MM/DD). Applies across all languages, so you can force day-first (DD/MM) reading — e.g. the Indian convention — on any voice.

Allowed values:
math_notationbooleanOptionalDefaults to false

Opt-in flag that reads digit-flanked math operators (5 x 3, 2 ^ 10, 6 ÷ 2) as words instead of leaving them for the default number reader. Off by default because in real traffic digit-flanked NxN is more often a product dimension, the 24x7 idiom, or a vehicle-registration code than an actual multiplication.

When true, the normalizer replaces the operator with the spoken word matched to number_pronunciation_language:

Glyphsen (default / fallback)himr
× x X *timesगुणागुणिले
÷ and spaced /divided byबटाभागिले
+plusप्लसअधिक
spaced - – −minusमाइनसवजा
=equalsबराबरबरोबर
^ **to the power ofकी घातची घात

Localized only for hi and mr; every other language falls back to the English words. The operator word follows number_pronunciation_language, not the synthesis language, so language=en, number_pronunciation_language=hi reads 6 x 7 as “छः गुणा सात”.

Matching rules: unambiguous glyphs (× ÷ * ^ ** = + and the wrong-glyph x/X) fire glued or spaced (5x3, 5 x 3). The ambiguous - – − and / fire only when space-padded, so 5-3 stays a range and 1/2 stays a fraction. See Math notation for the full lexicon, known limitations (product dimensions, 24x7 idiom, vehicle-reg codes), and EU-language localizations.

content_filterobjectOptional

Opt-in profanity filter for the submitted text. Off by default; passing this object is the only way to turn it on. The filter rewrites your text only with action: redact; otherwise it either lets the request through or rejects it before synthesis.

action: "reject" returns HTTP 400 with error_code: "CONTENT_FILTER_BLOCKED", the language checked and a match_count; the matched terms are never returned or logged. action: "flag" synthesizes normally and records the match.

Matching is whole-word, not substring. If no verdict is returned the request fails open and the audio is synthesized unfiltered.

See Content filter.

output_formatenumOptionalDefaults to pcm

Format of the returned audio. pcm is the lowest-latency option but requires a decoder to play; mp3 and wav are directly playable in browsers and most media players. The server default is pcm when the field is omitted — the API playground uses mp3 so the generated audio is directly playable.

Allowed values:
pronunciation_dictslist of stringsOptional

The IDs of the pronunciation dictionaries to use for speech generation. Available on both lightning_v3.1 and lightning_v3.1_pro.

word_timestampsbooleanOptionalDefaults to false

WebSocket-only feature. Accepted on this endpoint but ignored — no per-word timing information is returned in the sync HTTP or SSE response shape. To receive status: "word_timestamp" frames with per-word { id, word, start, end } data, use the WebSocket endpoint wss://api.smallest.ai/waves/v1/tts/live. See Word-level timestamps.

session_idstringOptionalformat: "^[a-zA-Z0-9_\-.]+$"<=128 characters

Optional client-provided session identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots are allowed. Max 128 characters. Echoed back in response headers as X-External-Session-Id.

request_idstringOptionalformat: "^[a-zA-Z0-9_\-.]+$"<=128 characters

Optional client-provided request identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots are allowed. Max 128 characters. Echoed back in response headers as X-External-Request-Id.

Response headers

X-Session-IdstringOptional

Internal session identifier (system-generated UUID).

X-Request-IdstringOptional

Internal request identifier (system-generated UUID).

X-External-Session-IdstringOptional

Echoed client-provided session_id (empty if not provided).

X-External-Request-IdstringOptional

Echoed client-provided request_id (empty if not provided).

Response

Synthesized speech retrieved successfully.

Errors

400
Bad Request Error
401
Unauthorized Error
500
Internal Server Error