Speech

Buy spoken audio from text. The endpoint has the shape of the OpenAI speech API, so an unchanged OpenAI client works. The response body is the audio file.

Quickstart

curl https://router.inference.ai.exchange/v1/audio/speech \
  -H "Authorization: Bearer sk-liquid-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini-tts",
    "input": "a cat on a bicycle",
    "voice": "alloy",
    "response_format": "mp3"
  }' --output speech.mp3
from openai import OpenAI

client = OpenAI(base_url="https://router.inference.ai.exchange/v1", api_key="sk-liquid-...")

with client.audio.speech.with_streaming_response.create(
    model="gpt-4o-mini-tts", voice="alloy", input="a cat on a bicycle"
) as response:
    response.stream_to_file("speech.mp3")

Examples

Operators of the exchange made example voice samples with each model. The page of a model in the console lists them. The app shows two here, each with its model and its prompt. Press play to hear one.

Find a model

A control works only when an offer for the model declares it. Read the model card before you send a control.

See Modalities for the card and the other filters.

Controls

A control works only when an offer declares it: speech.instructions for a style line and speech.turns for more than one speaker. voice is matched against the voices that an offer registered.

Voice

voice is optional. An offer that declared its voices must list the voice that you name. A request for a voice that no offer lists gets no offer.

Leave voice out to get the first voice of an offer that declared its voices. An offer that declared no voices cannot win a request that names none.

Style

Send instructions to set the style of the clip. Only an offer that declared speech.instructions can win.

{ "model": "<model>", "input": "Welcome back.", "instructions": "warm, slow", "voice": "alloy" }

Many speakers

Send input as an array of turns for a clip with more than one speaker. Each turn has its own voice and can have its own instructions. A turn with no voice uses the voice of the request. A turn with no instructions uses the instructions of the request.

{
  "model": "<model>",
  "input": [
    { "text": "Hello, Jane.", "voice": "Kore" },
    { "text": "Hi.", "voice": "Puck", "instructions": "tired" }
  ],
  "instructions": "cheerful"
}

Response

The body is the audio.

Billing

The price is for each character of the text of all the turns. The exchange counts characters, not bytes, so accented and non-Latin text does not cost more for each character. It does not count voice names or instructions. The cap is exactly the charge.

Request parameters

Field Type Required Description
model string Yes The model to buy, or a preset of the speech kind.
input string or array Yes The text to speak, or an array of turns {text, voice?, instructions?} for more than one speaker. At most 4,096 characters in all.
input_references array No A sample of a voice (role voice_sample) and its words (a text entry with the role voice_transcript). See Reference inputs.
voice string No The voice. See Voice.
instructions string No A style line, such as cheerful. At most 1,000 characters.
response_format string No mp3, opus, aac, flac, wav or pcm. The default is mp3.
speed number No From 0.25 to 4.0. It changes the length of the audio, not the cost.
quality string No A quality name such as hd. A deployment that prices that name apart charges its rate. Otherwise the base rate applies.
exchange object No Purchasing rules, such as cap_usd. See Purchasing rules.

Errors

Error Cause Fix
400 unsupported_model The model is not a speech model. Read /v1/models for kind: audio_speech.
400 unsupported_parameter No offer serves your voice or format, or none declared speech.instructions or speech.turns. param names it. Read parameters on the model card, or eligibility.excluded.

Speech in a chat answer

A chat model that speaks can answer with text and speech in one request. This is a different purchase from /v1/audio/speech: it is a chat job priced in tokens.

Send modalities with "audio" and an audio object. This is the OpenAI Chat Completions form.

{
  "model": "<model>",
  "stream": true,
  "modalities": ["text", "audio"],
  "audio": { "voice": "alloy", "format": "pcm16" },
  "messages": [{ "role": "user", "content": "Say hello" }]
}

Each stream chunk can hold choices[0].delta.audio. The first chunk has an id. A chunk has data (base64 audio), transcript (the text that the audio says), or both.

Which offers can win

The answer

Continue the talk

Send the earlier assistant turn with "audio": {"id": "…"}. The exchange keeps no audio, so the upstream that made the clip resolves the id.

Cost

Failure

The exchange can change to the next offer only before the first chunk. After the first chunk, a failure ends the job, and you pay for the output that you received.

Next steps