Speech-to-text
Buy a transcript of an audio file. The endpoint has the shape of the OpenAI transcriptions API, so an unchanged OpenAI client works. It also reads the JSON form that OpenRouter uses.
Only a deployment that is registered to transcribe can win the job. A chat deployment never wins one.
This job is not the same as Audio input. Audio input sends a clip to a chat model that can hear. This job returns the words of the clip.
Quickstart
curl https://router.inference.ai.exchange/v1/audio/transcriptions \
-H "Authorization: Bearer sk-liquid-..." \
-F model=whisper-1 \
-F [email protected] \
-F response_format=verbose_json
from openai import OpenAI
client = OpenAI(base_url="https://router.inference.ai.exchange/v1", api_key="sk-liquid-...")
with open("meeting.mp3", "rb") as audio:
transcript = client.audio.transcriptions.create(model="whisper-1", file=audio)
print(transcript.text)
Find a model
A control works only when an offer for the model declares it. Read the model card before you send diarize or keyterms.
GET /v1/models?kind=transcriptionlists the models as cards, withkindaudio_transcriptionandmodalitytranscription.parameterslistsdiarizeandkeytermswhen an offer declared them. A name that is not a key is not supported, so omit it.pricinggives the price of one second of audio.
See Modalities. If no offer declared a control that you sent, the answer is 400 unsupported_parameter, and param names the feature, such as transcription.diarize.
Controls
diarize and keyterms are offer features. language, timestamp_granularities and the audio limits are matched against what an offer registered.
Speakers and key terms
diarize and keyterms are offer features: transcription.diarize and transcription.keyterms. Only an offer that declared the feature can win a request that sets the field.
curl https://router.inference.ai.exchange/v1/audio/transcriptions \
-H "Authorization: Bearer sk-liquid-..." \
-F model=<model> \
-F [email protected] \
-F response_format=verbose_json \
-F diarize=true \
-F 'keyterms[]=Liquid Inference' \
-F 'keyterms[]=nano-USD'
- With
diarize, each segment has aspeaker, such asspeaker_0. Without it, a segment has nospeaker.diarizewithoutverbose_jsongets400 invalid_request. - With
keyterms, the transcript spells each term as you gave it. A list of more than 100 terms, or a term over 100 characters, gets400 invalid_request.
Audio by link
Send an https:// link in url and the exchange fetches the file.
{
"model": "<model>",
"input_references": [{ "type": "audio", "url": "https://example.com/call.wav" }]
}
- The link must use
httpsand name a public host. The exchange refuses an IP address, a host in its own network, a port that is not the default port, a login in the link, and a redirect to any of these. - The file has the same limits as a file that you send: 25 MB and two hours.
- The fetch stops after 20 seconds and three redirects.
- A link that the exchange cannot read gets
400, and the message says why. It does not repeat the link.
Audio limits
The exchange reads WAV, FLAC, MP3, Ogg, WebM, M4A and AAC from the bytes of the file. It does not trust the name or the format field.
- A file can be 25 MB and two hours at most.
- A file with no readable length gets
400, because the exchange cannot fix a cap without it. - An offer can also limit the container, the length (
max_duration_seconds) and the size (max_bytes). A request that breaks a limit does not reach that offer.
Response
json returns the text, the usage and the exchange block.
{
"text": "Welcome to the meeting.",
"usage": { "type": "duration", "seconds": 4 },
"exchange": { "...": "..." }
}
verbose_json adds language, duration (the seconds that the exchange measured), segments and words. A segment or a word is present only when you asked for that granularity. A segment has id, start, end and text, and a speaker with diarize.
{ "id": 0, "start": 0.0, "end": 3.4, "text": "Welcome to the meeting.", "speaker": "speaker_0" }
text returns plain text. Its exchange block comes back as JSON in the x-liquid-exchange response header.
Billing
The price is for each second of audio. The exchange reads the length from the file, so the cap is known before dispatch. It is exactly the most that you can pay.
The provider meters the seconds that it worked on. You pay that figure, never more than the cap.
Request parameters
Send multipart/form-data with the audio in file, or JSON with the audio in input_references.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | Yes | The model to buy, or a preset of the transcription kind. |
file |
file | Yes* | The audio, in a form body. |
input_references |
array | Yes* | One entry of type audio: a data:audio/ URL or an https:// link in url, or base64 in data and media_type. |
response_format |
string | No | json (the default), text or verbose_json. srt and vtt are not supported. |
timestamp_granularities |
array | No | segment, word or both. Only with verbose_json. An offer that cannot return them cannot win. |
diarize |
boolean | No | Label each segment with its speaker. Needs verbose_json. |
keyterms |
array | No | Up to 100 words or names, each up to 100 characters, that the transcript must spell as given. |
language |
string | No | An ISO 639-1 code such as en. An offer that declared its languages must list it. |
prompt |
string | No | A hint of vocabulary or style. At most 2,048 characters. |
temperature |
number | No | From 0 to 1. |
exchange |
object | No | Purchasing rules, such as cap_usd. See Purchasing rules. |
* Send file or input_references. Send one audio entry only.
stream is not supported. The transcript comes whole.
Errors
| Error | Cause | Fix |
|---|---|---|
400 |
No audio, a file that is too large or too long, or a length that the exchange cannot read. | Send a supported container under 25 MB and two hours. |
400 unsupported_model |
The model is not a transcription model. | Pick a model that lists audio input and a transcript output. |
400 unsupported_parameter |
No offer serves your language, format or granularity, or none declared a control. |
Read parameters on the model card, or eligibility.excluded. |
Next steps
- Audio input: send audio to a chat model.
- Speech: turn text into speech.
- Modalities: the map of all modalities.