Docs · Text to speech
One voice, and it stays that voice
One TTS alias: auto/tts, behind POST /v1/audio/speech. Two models sit behind it, and the alias moves between them on exactly one condition: the current model has been retired upstream. Not on a slow response. Not on a rate limit. Here is the shape it returns, and why it is not the shape you might expect.
The call
curl https://freemodel.online/v1/audio/speech \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{"model":"auto/tts","input":"Read this back to me.","voice":"zhimao"}'
You get JSON, not audio:
{
"object": "audio.speech",
"url": "https://dashscope-result-….oss-cn-beijing.aliyuncs.com/…",
"expires_at": "2026-09-28T12:40:00Z",
"format": "wav"
}
Fetch the url while it is live, or copy the file somewhere you control. It is a temporary object-store link, not a permanent CDN address.
import requests
r = requests.post(
"https://freemodel.online/v1/audio/speech",
headers={"Authorization": "Bearer sk-your-key"},
json={"model": "auto/tts",
"input": "Read this back to me.",
"voice": "zhimao"},
).json()
audio = requests.get(r["url"]).content
open("speech." + (r["format"] or "wav"), "wb").write(audio)
Why this is not the OpenAI shape
OpenAI's /v1/audio/speech streams audio bytes back on the same connection. Ours does not, and the reason is worth stating plainly.
The model behind the alias returns a temporary URL. To hand you bytes instead, the gateway would have to pull that audio down itself and stream it back out, meaning every generated second of audio crosses the machine twice. For a feature that is free to use, that is a lot of bandwidth spent on nothing but shape fidelity.
So the shape is hybrid: JSON, with the URL lifted to the top level and the format declared. It is the one place in this API where we knowingly diverge from OpenAI's contract, and it is documented rather than papered over.
If your code calls OpenAI's speech endpoint today, this is the one line you have to change: read url from the response instead of consuming a stream. Everything else (the endpoint path, the auth header, the model / input / voice fields) is unchanged.
What the alias will and will not do
| What happens upstream | What you get |
|---|---|
| Model retired (404 / 410) | The next model in the list answers |
| Timeout | An error. Same model. |
| Rate limited | An error. Same model. |
| Upstream 5xx | An error. Same model. |
Switching TTS models does not degrade your output, it changes it. Different voice, different pacing. If you are producing a 40-part audio series, a silent substitution halfway through is not a slightly worse result; it is a broken series you have to regenerate.
A retired model is the one case where falling through beats failing, because the alternative is no audio at all. So that case falls through. It is the only one.
The same rule governs every non-chat alias here. It is the opposite of pool-based routing, and it is why the embedding alias has a single candidate rather than a chain.
Request fields
| Field | Required | Notes |
|---|---|---|
model | Yes | auto/tts. A specific model name works too. |
input | Yes | The text to speak. |
voice | No | Defaults to zhimao. |
Bodies are capped at 25 MB and rejected with 413 before any upstream call. Content-Type: multipart/form-data is accepted as well as JSON; both reach the same handler.
Related capabilities
Same naming scheme, one alias per capability — all listed in /v1/models:
auto/asr
Speech to text.
auto/embed
1024-dimension vectors, one candidate.
auto/rerank
Reordering retrieved documents by relevance.
auto/image
Text to image.
auto/video
Text to video, asynchronous.
Sources
Every third-party figure quoted on this site was read from the vendor documentation linked below, on the date stated. None of these links are affiliate links and none of these vendors paid to be listed. If a number here disagrees with the page it came from, the page is right — tell us and it gets corrected.
- OpenRouter — credit-purchase fees and free-model rate limits
- OpenRouter — rate-limit reference
- OpenRouter — public model list
- LiteLLM — licence, deployment options and supported models
- Cloudflare AI Gateway — features and pricing
- Vercel AI Gateway — features
- Portkey — plans
- Helicone — plans
- Model Context Protocol — specification
- OpenAI Python SDK — base_url and OPENAI_BASE_URL
- Anthropic Messages API — request format
Key numbers
- 1 个端点
- 1 个别名
- 0 个音频字节返回
- 1 endpoint:
POST /v1/audio/speech; 1 alias:auto/tts. - 0 audio bytes in the response — you get JSON with
url,expires_atandformat. - 1 fetch to a temporary object-store URL, which expires; copy the file if you need it later.
- Output format in the example: wav; voice name is a request field.
How to use it, step by step
- Step 1. POST
{"model":"auto/tts","input":"…","voice":"zhimao"}to/v1/audio/speech. - Step 2. Read
urlfrom the JSON response and fetch it beforeexpires_at. - Step 3. Store the audio file yourself — the link is temporary, not a CDN address.
FAQ
Why is the response JSON instead of audio bytes?
The upstream returns an object-store link. Sending that JSON through keeps the response small and avoids proxying the file twice.
What happens if I fetch the url late?
It expires. The expires_at field says when; after that, re-request the synthesis.
Can the voice change under the alias?
The voice is a request field you send. The model behind auto/tts changes only when the current one is retired upstream.
When to use it — and when not to
Use it for narration: article-to-audio, course modules, IVR prompts, accessibility versions of written content. One voice, long text, predictable output.
Do not use it for voice cloning, multi-speaker dialogue, or emotion control. The alias exposes a single consistent voice on purpose; those features belong to providers that sell them explicitly.
Limits worth designing around
- One voice per alias: the voice will not change mid-document, which is the point. If you need two voices, make two calls and stitch.
- Text length per request: split long articles on sentence boundaries, not mid-sentence, and keep a small pause between segments.
- Output is a URL: download and store the audio yourself; treat the URL as temporary.
- Numbers and names: read the text before synthesis. A model may pronounce an abbreviation differently than you expect; spell it out when accuracy matters.
- Data path: the text is sent to the upstream provider. Do not synthesize confidential documents without checking the provider's policy.
Cost and latency
Pricing is usually per character or per 10k characters. Estimate by document length: a 1,500-character article is one or two calls, a 30-minute audiobook is dozens. Generation is slower than real time for long text, so queue it.
Cache by content hash. Re-synthesizing an unchanged article on every deploy is the most common waste in an audio pipeline.
Two more questions
Can I get a different voice? Not through this alias. Pin a model that offers the voice you need, or use a provider with a voice catalog.
How do I check quality? Listen to the first 30 seconds and the last 30 seconds of every new document; boundary errors and truncation show up at the ends, not in the middle.