Narration
POST /v1/synthesize with workload=narration: long-form TTS, voice settings, sample rate, chunking.
Server-side TTS tuned for reading prose aloud - audiobooks, articles, video voiceover. Set workload: "narration" in the /v1/synthesize body:
curl -X POST https://api.speko.dev/v1/synthesize \
-H "Authorization: Bearer $SPEKO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Chapter one. The harbor was quiet that morning, and the first ferry moved slowly through the mist.",
"intent": { "language": "en" },
"workload": "narration"
}' \
--output chapter-1.pcmWhat workload: "narration" does:
- Applies narration defaults from the param registry where the winning provider has them - for ElevenLabs,
voice_settings: { stability: 0.5, similarity_boost: 0.75, use_speaker_boost: true }. Your explicit values always override defaults. - Prefers a 24 kHz output ladder when you set no
sampleRateand at least one candidate serves that rate. An explicitsampleRateremains the hard contract. - Reports the applied param names in the
X-Speko-Applied-Paramsresponse header; dropped params and validation warnings arrive inX-Speko-Warnings.
Voice settings
Per-provider generation knobs go in providerOptions. They are validated up front and apply only when that provider serves the request - on failover to another provider they never cross:
{
"text": "...",
"intent": { "language": "en" },
"workload": "narration",
"providerOptions": {
"elevenlabs": {
"voice_settings": {
"stability": 0.65,
"similarity_boost": 0.8,
"style": 0.2,
"use_speaker_boost": true
}
}
}
}| Provider | Param | Type | Values | Effect |
|---|---|---|---|---|
| ElevenLabs | voice_settings | object | stability 0-1, similarity_boost 0-1, style 0-1, use_speaker_boost bool, speed 0.7-1.2 | Overrides the voice's per-request generation settings. |
| ElevenLabs | apply_text_normalization | enum | auto, on, off | Controls provider-side text normalization. |
| MiniMax | volume | number | 0.5-2 | Output volume multiplier. |
| MiniMax | pitch | integer | -12 to 12 | Shifts pitch by semitones. |
| Cartesia | speed | number | 0.6-1.5 | Speaking-rate multiplier. |
| Cartesia | volume | number | 0.5-2 | Output volume multiplier. |
| Fish Audio | latency | enum | normal, low | Normal quality or low-latency generation. |
| Bland | expressiveness | number | 0-1 | Expressive variation. |
| Bland | stability | number | 0-1 | Consistency in generated speech. |
Setting both the top-level speed and a provider speed spelling (voice_settings.speed, Cartesia speed) is rejected as canonical_collision - set one. Full registry and validation rules: Provider params.
Pick a voice explicitly with voice (browse via GET /v1/voices) and pin the provider via constraints.allowedProviders.tts when a long run must stay on one voice.
Long-form text
- The endpoint caps
textat 50,000 characters per call. - Upstream providers enforce their own per-request character limits below that cap, and very long inputs raise time-to-first-audio; the gateway fails a candidate over if it produces no audio within 10 seconds.
- Server-side chunking of long scripts into one stitched audio stream is a follow-up. Today, chunk the script yourself (paragraph boundaries work well) and call
/v1/synthesizeper chunk. Set an explicitsampleRateso every chunk - including any failover - returns the same rate, then concatenate the PCM.