Audio
Transcribe audio and generate speech.
/v1/audioTurn speech into text, and text into speech. These routes follow the OpenAI Audio API, so client.audio.transcriptions.create and client.audio.speech.create work unchanged with the base URL https://demo-api.routerplus.com/v1.
| Route | Alias | What it does |
|---|---|---|
POST /v1/audio/transcriptions | POST /audio/transcriptions | Returns the text of an audio file |
POST /v1/audio/speech | POST /audio/speech | Returns spoken audio for a text, streamed as it is made |
Examples
curl https://dev2-api.routerplus.com/v1/audio/transcriptions \
-H "Authorization: Bearer $ROUTERPLUS_API_KEY" \
-F model=whisper-1 \
-F response_format=srt \
-F [email protected]curl https://dev2-api.routerplus.com/v1/audio/speech \
-H "Authorization: Bearer $ROUTERPLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4o-mini-tts", "input": "Your order has shipped.", "voice": "coral"}' \
--output speech.mp3from openai import OpenAI
client = OpenAI(base_url="https://demo-api.routerplus.com/v1", api_key="tm_vk_...")
with open("meeting.mp3", "rb") as f:
transcript = client.audio.transcriptions.create(model="gpt-4o-transcribe", file=f)
print(transcript.text)
with client.audio.speech.with_streaming_response.create(
model="tts-1", voice="alloy", input="Your order has shipped."
) as response:
response.stream_to_file("speech.mp3")Send your key as Authorization: Bearer tm_vk_... or as x-api-key: tm_vk_.... A missing or invalid key returns 401.
Models
| Model | Route | Price | Billed on |
|---|---|---|---|
gpt-4o-transcribe | transcriptions | $2.50 per 1M input tokens, $10.00 per 1M output tokens | usage.input_tokens and usage.output_tokens |
gpt-4o-mini-transcribe | transcriptions | $1.25 per 1M input tokens, $5.00 per 1M output tokens | usage.input_tokens and usage.output_tokens |
whisper-1 | transcriptions | $0.006 per minute ($0.0001 per second) | seconds of audio, rounded up |
gpt-4o-mini-tts | speech | $0.60 per 1M input tokens, $12.00 per 1M audio output tokens | the tokens the provider reports |
tts-1 | speech | $15.00 per 1M characters | characters of input |
tts-1-hd | speech | $30.00 per 1M characters | characters of input |
OpenAI serves all six models. GET /v1/models?output_modalities=transcription lists the transcription models, and ?output_modalities=audio lists the speech models.
POST /v1/audio/transcriptions
Request
The body is multipart/form-data. The audio file is at most 25 MiB. A larger file is a 413. RouterPlus checks every rule below before it reserves money or calls a provider. A refused request has no ledger row and no charge.
| Field | Type | Behavior |
|---|---|---|
file | file, required | The audio: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav or webm. |
model | string, required | A transcription model id. A speech, chat, image, video, decision or embeddings model is a 400 that names its own route. An id that is not in the catalog is a 404. |
response_format | string | json (the default), text, verbose_json, srt or vtt. gpt-4o-transcribe and gpt-4o-mini-transcribe take json and text only. |
language | string | The language of the audio as an ISO-639-1 code, for example en. |
prompt | string | Text that guides the style or spelling of the transcript. |
temperature | number | From 0 to 1. |
timestamp_granularities[] | string | segment or word. With whisper-1 and verbose_json only. |
provider | JSON string | Routing controls. See Provider routing. |
RouterPlus drops any other field and names it in the x-tm-dropped-params header. With provider.require_parameters: true, a dropped field is a 400. stream=true is a 400: the route returns one response.
Response
json:
{
"text": "Hello there.",
"usage": { "type": "tokens", "input_tokens": 1500, "output_tokens": 40, "total_tokens": 1540, "cost": 0.00415 }
}whisper-1 reports the billed seconds:
{
"text": "Hello there.",
"usage": { "type": "duration", "seconds": 62, "cost": 0.0062 }
}| Format | Content type | Body |
|---|---|---|
json | application/json | text and usage |
verbose_json | application/json | text, language, duration, segments (and words when asked for), and usage |
text | text/plain | The transcript |
srt | text/plain | SubRip subtitles, one cue per segment |
vtt | text/vtt | WebVTT subtitles, one cue per segment |
usage.cost is the charge in USD for the request. The text, srt and vtt formats do not carry it. GET /v1/generation shows it for every request.
POST /v1/audio/speech
Request
The body is JSON, at most 1 MB.
| Parameter | Type | Behavior |
|---|---|---|
model | string, required | A speech model id. |
input | string, required | The text to speak. At most 4,096 characters. |
voice | string, required | A voice name, for example alloy, coral or nova. |
response_format | string | mp3 (the default), opus, aac, flac, wav or pcm. |
speed | number | From 0.25 to 4. The default is 1. |
instructions | string | How to speak, for example "calm and slow". gpt-4o-mini-tts only. The tokens count as input. Another model drops the field. |
stream_format | string | audio only. Any other value is a 400. |
provider | object | Routing controls. See Provider routing. |
Response
The body is the audio file in response_format. RouterPlus sends each part of the audio when it arrives from the provider, so playback can start before the speech is complete.
| Format | Content type |
|---|---|
mp3 | audio/mpeg |
opus | audio/opus |
aac | audio/aac |
flac | audio/flac |
wav | audio/wav |
pcm | audio/pcm (raw 24 kHz, 16-bit, mono samples) |
The response does not carry the cost. GET /v1/generation shows it.
Billing
- 01Before the call, RouterPlus holds an estimate of the cost on your balance.
- 02After the call, it charges the billed units from the Models table and releases the rest of the hold.
- 03If the provider reports no usage, RouterPlus charges the estimate it held.
The hold for each model:
| Model | Hold |
|---|---|
gpt-4o-transcribe, gpt-4o-mini-transcribe | 16,000 input tokens and 2,000 output tokens |
whisper-1 | The length of the audio. For a wav or mp3 file, RouterPlus reads the length from the file. For another format, it assumes 1,000 bytes per second. |
gpt-4o-mini-tts | The input text at 3 bytes per token, and 2 audio tokens per character divided by speed |
tts-1, tts-1-hd | The characters of input |
A failed attempt costs nothing.
Routing and failover
RouterPlus picks the provider with the same rules as chat. Guardrails apply: a model your guardrail does not allow is a 403 with error_type: "guardrail_blocked".
If a provider fails before it answers (a 5xx, a 429 or a timeout), RouterPlus tries the next provider of the model. For speech, failover stops at the first byte of audio. After that byte, the answer comes from that provider. x-tm-attempts gives the number of attempts. x-tm-provider names the provider that answered.
For agents: /docs/api-audio.md and /llms.txt