Other clients

/v1/audio/speech

Speech over HTTP, shaped like OpenAI's audio/speech: the OpenAI SDK works with the base URL and key changed.

Request#

POST https://api.ttscacherouter.dev/v1/audio/speech with your router API key as Authorization: Bearer tcr_…. The router splits input into sentences, serves each one your org has synthesized before from the cache, and synthesizes the rest with the provider key stored for your org. Audio streams back as each sentence is ready.

import osfrom openai import OpenAIclient = OpenAI(    base_url="https://api.ttscacherouter.dev/v1",    api_key=os.environ["TTS_CACHE_ROUTER_API_KEY"],)with client.audio.speech.with_streaming_response.create(    model="sarvam/bulbul:v3",    voice="shubh",    input="नमस्ते, मैं सिटी हॉस्पिटल से प्रिया बोल रही हूँ।",    response_format="mp3",    extra_body={"language": "hi-IN"},) as response:    response.stream_to_file("speech.mp3")

Provider-specific fields go in the body; with the OpenAI SDK, pass them in extra_body.

Body#

modelstringRequired
<provider>/<model>: sarvam/bulbul:v3, sarvam/bulbul:v4-flash, raya/standard, raya/m1, or an ElevenLabs model such as elevenlabs/eleven_flash_v2_5 (see Models and options).
inputstringRequired
The text to speak, up to 20,000 characters.
voicestringRequired
A Sarvam speaker, a Raya voice id or an ElevenLabs voice id, belonging to the model. See Models and options.
languagestringRequired; optional for ElevenLabs
The provider’s language code: hi-IN for Sarvam, hi for Raya, en for ElevenLabs (which detects the language when it is left out).
response_formatstringDefault "mp3"
See Formats.
speednumberDefault 1.0
Sarvam 0.5–2.0, Raya 0.5–1.5. Refused for ElevenLabs: use voice_settings.speed.
sample_rateintegerDefault 24000
8000, 16000, 22050 or 24000; Sarvam also 32000, 44100 or 48000, where each sentence arrives only once it is fully synthesized and bitrate is fixed at 128k. ElevenLabs: 8000–48000 for pcm and wav; mulaw and alaw default to their only rate, 8000.
temperaturenumberSarvam only
0.01–1.0, default 0.6.
dict_idstringSarvam only
A Sarvam pronunciation dictionary to apply.
pitchnumberSarvam bulbul:v4-flash only
-0.5 (deeper) to 0.5 (higher), default 0.
loudnessnumberSarvam bulbul:v4-flash only
0.1–2.5, default 1.0.
enable_preprocessingbooleanSarvam bulbul:v4-flash only
Normalize numbers and English words in the text before synthesis. Default false.
bitratestringSarvam, ElevenLabs
Sarvam, for mp3 and aac: 32k, 64k, 96k, 128k or 192k, default 128k. ElevenLabs, for mp3: 32k at 22050 Hz, 48k at 24000 Hz, 32k–192k at 44100 Hz (default 128k).
voice_settingsobject | nullElevenLabs only
stability and similarity_boost (0–1, both required), and optionally style (0–1), speed (0.7–1.2) and use_speaker_boost. Null: the voice’s stored settings.
apply_text_normalizationstringElevenLabs only
auto (default), on or off.
apply_language_text_normalizationbooleanElevenLabs only
Language-specific normalization (Japanese).
enable_ssml_parsingbooleanElevenLabs only
Parse SSML tags. Default false.
enable_loggingbooleanElevenLabs only
false for ElevenLabs’ zero-retention mode (enterprise accounts). Default true.
pronunciation_dictionary_locatorsarrayElevenLabs only
Up to 3 {pronunciation_dictionary_id, version_id}.
stream_format"audio"Default "audio"
The body is the audio itself. sse is not supported.

Any other field, such as OpenAI’s instructions, is a bad_request.

Formats#

Every format is produced by the provider itself; the router never re-encodes audio. Only formats whose sentences join into one valid stream are offered.

response_formatSarvamRayaElevenLabs
pcmYesYesYes
wavYesYesYes
mp3YesNo22050, 24000, 44100 Hz
aacYesNoNo
mulawYesYes8000 Hz
alawYesNo8000 Hz
flac, opusNoNoNo
  • pcm is raw 16-bit little-endian mono at sample_rate; wav is the same with a WAV header for streaming (its size fields are left open).
  • mulaw and alaw are 8-bit G.711 at sample_rate, for telephony.
  • Any other combination is refused with HTTP 400.

Content types: audio/pcm, audio/wav, audio/mpeg, audio/aac, audio/mulaw, audio/alaw.

Errors#

An error before any audio is a JSON body with an HTTP status. The codes are the WebSocket protocol's.

JSON
{  "error": {    "code": "provider_rejected",    "message": "…",    "retryable": false,    "provider_status": 403  }}
bad_requestHTTP 400, not retryable
The request failed validation or a message arrived out of order. The message says which field or rule.
unauthorizedHTTP 401, not retryable
The API key is missing, wrong or deleted, or its org is disabled.
insufficient_creditsHTTP 402, not retryable
Your org is out of credit, so the router refuses new connections and requests until you buy more. Connections already open carry on.
provider_key_missingHTTP 400, not retryable
Your org has no key stored for the provider. Add one under Provider keys.
provider_rejectedHTTP 400, not retryable
The provider refused the request, e.g. a wrong stored provider key or an unknown voice. The provider’s message is passed through.
provider_rate_limitedHTTP 429, retryable
Your own quota at the provider is exhausted.
provider_unavailableHTTP 502, retryable
The provider returned a server error, or the connection to it failed or closed unexpectedly.
provider_timeoutHTTP 504, retryable
The provider took too long to send audio.
internalHTTP 500, retryable
The router failed.