Text to speech

Turn text into audio — Persian on one engine, twenty-three other languages on another, chosen for you automatically.

POST /v1/audio/speech takes text and returns audio bytes, in the same shape OpenAI's endpoint uses. Behind it are two different engines picked by language, not one model that speaks everything.

POST/v1/audio/speech
ParameterTypeDescription
input
Required
stringThe text to speak. 8000 characters max.
model
Required
stringThe only deployment name, larsa-tts. Required — the gateway uses it to route the request, and a call that omits it fails.
Default: larsa-tts
voice
Required
stringRequired, even though the value itself has no effect — each engine speaks with exactly one voice right now, so any value you send, including OpenAI voice names like alloy, is accepted and ignored. Omitting the field is not the same as sending an ignored value: the request fails.
Default: default
language
Optional
stringWhich engine, and how the text is pronounced — see below. Auto-detected from the text when omitted, which is reliable for Persian and risky for everything else.
response_format
Optional
stringmp3 · opus · aac · flac · wav.
Default: mp3
guard
Optional
booleanSynthesise, transcribe the result back, and regenerate if the words don't match closely enough — see below. Costs a full extra round trip through speech-to-text.
Default: false
max_retries
Optional
integerOnly matters with guard: true — the best of up to max_retries + 1 attempts is returned.
Default: 2
Omit either one and you get a bare 500
model and voice must both be present in the JSON body — not just input. Leave either one out and the response is {"error": {"message": "Internal server error"}}, 76 bytes, with nothing to say which field was missing. There is no way to work it out from the response itself; every sample below sends both, every time.
Synthesising speech
curl -s https://api.console.larsa.larsima.com/v1/audio/speech \
  -H "Authorization: Bearer $LARSA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "larsa-tts",
    "voice": "default",
    "input": "Se dictará sentencia en un plazo máximo de veinte días.",
    "language": "es",
    "response_format": "mp3"
  }' --output speech.mp3

Two engines, chosen by language

No open engine covers Persian and the European languages at usable quality together, so this deployment doesn't pretend one does — it routes.

LanguageEngineNote
PersianAava (Orpheus 3B, Apache-2.0)The only engine used for Persian.
23 other languagesChatterbox Multilingual (MIT)Arabic, Chinese, Danish, Dutch, English, Finnish, French, German, Greek, Hebrew, Hindi, Italian, Japanese, Korean, Malay, Norwegian, Polish, Portuguese, Russian, Spanish, Swahili, Swedish, Turkish. Not Persian.
The multilingual engine does not speak Persian
Persian is not one of Chatterbox's 23 trained languages, on purpose — forcing Persian text through it measured 95% round-trip word error rate: Persian-shaped noise, not an accent. Persian only ever goes to Aava.

Say the language — don't rely on guessing

Without language, the engine is picked by counting Persian characters: more than a quarter of the text and it goes to Aava; otherwise it goes to Chatterbox pronouncing English — regardless of what language the text is actually in. Spanish text sent with no language field is read aloud with English phonemes. Set language to the two-letter code (es, fr, de, …) for anything that isn't Persian or English, every time.

Response headers

HeaderMeaning
X-Lardad-Engineaava or chatterbox.
X-Lardad-LanguageThe language actually used to pick the engine.
X-Lardad-DurationLength of the audio, in seconds.
X-Lardad-ElapsedWall-clock time the request took, in seconds.
X-Lardad-Guard-ScoreOnly present with guard: true — the fraction of input words the readback recognised, 0 to 1.

Measured quality, and the failure both engines share

Quality here means round-trip word error rate: synthesise a sentence, transcribe the audio back with the speech-to-text service, and compare to the original. Aava scored 22.0% on the speaker's own recordings — clearer than the human reading the same text, which scored 41.5%. Chatterbox on Spanish scored 2.3%. On French it was inconsistent: 0.0% on one sentence and 113% on another, where it read the sentence correctly and then kept going, inventing words that were never in the input.

Neither engine always stops on its own
Roughly one Persian generation in five collapsed into unrelated words, and the French example above kept talking after a correct reading. Neither failure raises an error — the response is a normal audio file that happens to say the wrong thing. guard: true is the check: it listens to what it just generated, and regenerates when the words don't come back close enough. It costs a second or two more; for anything a person hears unattended, it's worth every millisecond.
cURL
curl -s https://api.console.larsa.larsima.com/v1/audio/speech \
  -H "Authorization: Bearer $LARSA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "larsa-tts",
    "voice": "default",
    "input": "مهلت تجدیدنظرخواهی بیست روز از تاریخ ابلاغ است.",
    "guard": true,
    "max_retries": 2
  }' --output speech.mp3 -D -

# X-Lardad-Engine: aava
# X-Lardad-Language: fa
# X-Lardad-Guard-Score: 0.94
Navigate Open esc Close