Text to Speech (TTS)
Takes a string, returns natural-sounding audio. Compatible with the OpenAI audio/speech format.
Qevron has two local TTS engines: blab-fast (fast) and blab-pro (premium). Every other TTS id is a permanent alias pointing at one of these two.
Available models
| Model | Engine | Sample rate | Measured latency¹ | Price | Use where |
|---|---|---|---|---|---|
blab-fast (default) | Supertonic v3 | 44.1 kHz | ~0.2–0.5 s (median ~0.3) | $6 / 1M chars | Realtime agents, telephony, streaming, high volume |
blab-pro (premium) | VoxCPM2 | 48 kHz | ~0.5–0.8 s (median ~0.7) | $12 / 1M chars | Promos, audiobooks, voice cloning, style direction |
tts-1 | OpenAI | — | — | OpenAI rate | Only if an OpenAI-keyed channel is configured |
¹ Measured on this deployment, from the same host, end-to-end (non-streaming) for a ~50-character Turkish sentence. Longer input takes proportionally longer; use streaming to get first audio sooner.
Aliases
The older model ids were not removed — they keep working as permanent aliases:
| What you send | What actually runs |
|---|---|
blab-stable | blab-fast |
blab-expressive | blab-pro |
blab-tts | blab-pro |
Removed Piper models
blab-fast-tr-naz and blab-fast-en-emma were fully removed on 2026-08-10 and now return 404. Migrate any code using those ids to blab-fast plus a voice id.
curl
curl https://app.qevron.ai/v1/audio/speech \
-H "Authorization: Bearer $QEVRON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "blab-fast",
"input": "Hello, this audio was produced with Qevron.",
"voice": "emma"
}' --output out.wavPython (openai SDK)
from openai import OpenAI
client = OpenAI(api_key="sk-...", base_url="https://app.qevron.ai/v1")
resp = client.audio.speech.create(
model="blab-fast",
input="Qevron serves your own models through one API.",
voice="emma",
)
resp.stream_to_file("out.wav")Which model when?
blab-fast— your default. Phone agents, live chat, streaming reads, bulk generation. Milliseconds-scale synthesis across 30 languages. Thequalityfield (standard/high/max) trades speed for fidelity via the engine's diffusion step count.blab-pro— when quality and voice identity matter. 48 kHz studio grade, context-aware reading, instant voice cloning, prompt-based voice design (voice_description) and natural-language style direction (instruction). Roughly double the latency and double the price.tts-1— only if an OpenAI-keyed channel exists; the voices are OpenAI's.
Telephony and realtime lanes
blab-stable-voice and blab-stable-live are separate model ids that pin the same Supertonic engine to dedicated GPU lanes for telephony and realtime use, so batch jobs cannot block the queue. For general-purpose integrations use blab-fast.
The voice parameter
voice is a voice id, not a language code. It is optional — omit it and the engine uses its own default voice.
{"model": "blab-pro", "input": "Hello world", "voice": "sinan"}- The full list of ids: TTS Voice Roster (47 catalogued voices for
blab-pro, 40 forblab-fast). - Live listing:
GET /v1/audio/voices?model=blab-fast→ see Audio API. - The roster is engine-specific:
blab-proids are not valid onblab-fast. - Voices you clone yourself appear in the same listing and are visible only to your group.
An unknown id behaves DIFFERENTLY on the two engines
A voice that is not in the roster (including the legacy "tr" / "en" language codes):
| engine | result |
|---|---|
blab-fast (blab-stable) | HTTP 200 — no error; silently reads with the engine's default voice |
blab-pro (blab-expressive, blab-tts) | HTTP 400 — the request is rejected |
The silent fallback exists only on blab-fast, and that is the dangerous half: a wrong id still looks like a success, but the speaker is not the one you asked for. Ids are not portable between engines (naz is blab-fast only, nisan is blab-pro only) — always verify against GET /v1/audio/voices for the model you are calling.
Audio format (response_format)
| Format | blab-fast | blab-pro |
|---|---|---|
wav (default) | ✓ 44.1 kHz | ✓ 48 kHz |
mp3 | ✓ | ✓ |
pcm | ✓ raw int16 | ✓ raw int16 (24 kHz stream) |
opus / aac / flac | ✗ — silently returns WAV | ✗ — returns 400 |
The two engines differ here: blab-fast silently downgrades an unsupported format to WAV, while blab-pro fails loudly. Choose the file extension from the actual response content, not from what you asked for.
Streaming
stream = client.audio.speech.create(
model="blab-fast",
input="A long passage of text...",
voice="emma",
stream=True,
)
with open("out.wav", "wb") as f:
for chunk in stream.iter_bytes():
f.write(chunk)For realtime agents, response_format: "pcm" gives a raw int16 stream you can feed straight into an audio device or phone leg.
Legacy stream_format parameter
Before v2.2.0 you had to pass OpenAI's original stream_format: "sse" explicitly. As of v2.2.0 qevron auto-bridges stream: true (the SDK shape) → stream_format: "sse". Both work; an explicit stream_format still wins.
Voice cloning
blab-pro clones a voice from a reference clip in seconds:
curl -X POST "https://app.qevron.ai/v1/audio/voices?model=blab-pro" \
-H "Authorization: Bearer $QEVRON_API_KEY" \
-F "label=Host Voice" \
-F "file=@reference.wav"Put the returned id straight into the voice field. The reference clip must be 3–60 seconds. Passing the clip's exact text as transcript upgrades the clone to prompt-continuation ("ultimate") mode for sharper similarity. Details: Audio API.
Troubleshooting
- Silent or corrupt file → set
Content-Type: application/json; send JSON, not form-data. - The voice never changes → the
voiceid you sent may not exist on that engine, so it silently fell back to the default. Verify withGET /v1/audio/voices?model=<model>. 404 model not found→ you are using a removed id (blab-fast-tr-naz,blab-fast-en-emma). Useblab-fastplus avoice.- Asked for
opus/flac, got WAV →blab-fastsilently downgrades unsupported formats. - MP3 or WAV? → WAV by default. Add
"response_format": "mp3"for MP3.
Next: TTS Voice Roster · Audio API · STT — speech to text