Loly 3.5
Text-to-Speech (Bytes)
Uses the same JSON fields and permissions as batch generation, but returns the completed file directly.
POST
/api/v1/tts/bytesOn this page
Code examples
curl -X POST https://studio.evomlabs.com/api/v1/tts/bytes \
-H "Authorization: Bearer vc_sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Xin chào","language":"vi","format":"wav"}' \
--output hello.wavRequest
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
text | string | Yes | - | Text to speak, not empty, up to 5,000 characters. |
voice_id | string | No | - | Required with an account key. Omit with a voice key; if provided, it must match the key-bound voice. |
language | string | No | auto | auto, or one code or full name from the 646-language catalog. |
format | "mp3" | "wav" | No | mp3 | Exactly mp3 or wav. The returned container and MIME match this value. |
speed | number | No | 1.0 | Playback rate, clamped to 0.5 to 1.5. Ignored when duration is set. |
duration | number | null | No | null | Generate audio of exactly this many seconds, from 0.5 to 30. Omit it, or send null, to let the model set the length from the text. Overrides speed; out-of-range values are rejected rather than clamped. |
cfg_value | number | No | 2.0 | How closely to follow the reference voice. A finite number from 0.0 to 4.0, including 0. |
dit_steps | integer | No | 10 | Diffusion steps. An integer from 0 to 64, including 0. |
The allowance is deducted up front by text.length, including any whitespace in the string you send.
Fixed output duration
duration replaces the model's own length estimate with an exact target, which is why it overrides speed rather than combining with it. Three things to know: the saved file is not exactly that long, because postprocess_output trims silence and then pads 0.1s onto each edge — send postprocess_output: false when you need the closest match; the ceiling sits below the point where the model switches to chunked generation and re-estimates length per chunk, so a value it cannot honour is refused instead of accepted; and /sse and the WebSocket ignore the field, because they synthesise one sentence per model call and a single length has nowhere to apply. It is part of the price: billable characters are max(text length, duration × characters-per-second), so leaving duration unset costs exactly what it always did, and asking for audio longer than the text naturally needs costs more.
Response
Important
A successful response is binary audio, not JSON.
| Header | Value | Meaning |
|---|---|---|
Content-Type | audio/wav | audio/mpeg | WAV for wav, MPEG audio for mp3. |
Content-Disposition | attachment filename | Suggested oriagent.wav or oriagent.mp3 filename. |
X-OriAgent-Format | wav | mp3 | The selected output format. |
X-OriAgent-Sample-Rate | integer Hz | Present only when the backend provides it. |
X-OriAgent-Chars-Deducted | integer | Exactly text.length charged for the request. |
Errors
REST failures use the documented error envelope. Handle the error code instead of matching the human-readable message.
Error codesWas this page helpful?