> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opper.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Audio

> Turn text into speech and speech into text through one gateway and key.

The gateway covers both directions of audio with two synchronous endpoints:

* **Text to speech** — `POST /v3/audio/speech` turns text into spoken audio.
* **Speech to text** — `POST /v3/audio/transcriptions` turns audio into a transcript.

Both are provider-agnostic: `model` selects the provider, a small set of fields is normalized for you, and anything model-specific goes in `parameters`. For live, two-way voice conversations, use [Realtime](/build/realtime/quickstart) instead.

## Text to speech

Pass a `model` and the `input` text. The response carries the audio inline as base64 and, by default, a stored `file_id` + presigned `url`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -sX POST https://api.opper.ai/v3/audio/speech \
    -H "Authorization: Bearer $OPPER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/tts-1",
      "input": "Hello from Opper.",
      "voice": "alloy",
      "format": "mp3"
    }'
  ```

  ```python Python theme={null}
  import os, base64, requests

  r = requests.post(
      "https://api.opper.ai/v3/audio/speech",
      headers={"Authorization": f"Bearer {os.environ['OPPER_API_KEY']}"},
      json={
          "model": "openai/tts-1",
          "input": "Hello from Opper.",
          "voice": "alloy",
          "format": "mp3",
      },
  )
  r.raise_for_status()
  audio = r.json()["audio"]
  open("speech.mp3", "wb").write(base64.b64decode(audio["b64_json"]))
  print("saved speech.mp3", "·", audio.get("file_id"))
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": "spch_...",
  "model": "openai/tts-1",
  "created": 1716124800,
  "audio": {
    "b64_json": "SUQzBAAAAAA...",
    "mime_type": "audio/mpeg",
    "file_id": "file_...",
    "url": "https://...presigned..."
  },
  "usage": { "cost": 0.0009, "characters": 17 }
}
```

| Field        | What it does                                                                                   |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `model`      | Required. The TTS model, e.g. `openai/tts-1`.                                                  |
| `input`      | Required. The text to speak.                                                                   |
| `voice`      | Provider voice; empty uses the model's default. Validated against the model's declared voices. |
| `format`     | `mp3` (default), `wav`, `opus`, `aac`, `flac`, or `pcm`.                                       |
| `speed`      | `0.25`–`4.0` where the model supports it.                                                      |
| `store`      | Persist the audio and return a `file_id` + `url`. Defaults to true; respects retention rules.  |
| `parameters` | Opaque per-provider passthrough.                                                               |

Speech is billed per input character.

## Speech to text

Pass a `model` and an `audio` source: a `file_id` from a previous generation or upload, an https URL, or a data-URI (max 25 MB decoded).

<Note>
  A `file_id` lets you transcribe audio you already have on Opper — a clip you uploaded, or speech you just generated with `/v3/audio/speech` — without re-sending the bytes. See [Files](/build/multimodal/files) for how files work, lifecycle, and storage quotas.
</Note>

```bash Transcribe a file_id theme={null}
curl -sX POST https://api.opper.ai/v3/audio/transcriptions \
  -H "Authorization: Bearer $OPPER_API_KEY" -H "Content-Type: application/json" \
  -d '{ "model": "openai/whisper-1", "audio": "file_abc123" }'
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -sX POST https://api.opper.ai/v3/audio/transcriptions \
    -H "Authorization: Bearer $OPPER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/whisper-1",
      "audio": "https://example.com/meeting.mp3",
      "language": "en"
    }'
  ```

  ```python Python theme={null}
  import os, requests

  r = requests.post(
      "https://api.opper.ai/v3/audio/transcriptions",
      headers={"Authorization": f"Bearer {os.environ['OPPER_API_KEY']}"},
      json={
          "model": "openai/whisper-1",
          "audio": "https://example.com/meeting.mp3",
          "language": "en",
      },
  )
  r.raise_for_status()
  print(r.json()["text"])
  ```
</CodeGroup>

```json Response theme={null}
{
  "id": "trsc_...",
  "model": "openai/whisper-1",
  "created": 1716124800,
  "text": "Full transcript here...",
  "language": "en",
  "duration": 42.5,
  "segments": [
    { "start": 0.0, "end": 3.2, "text": "Full transcript here..." }
  ],
  "usage": { "cost": 0.004, "seconds": 42.5 }
}
```

| Field        | What it does                                                                           |
| ------------ | -------------------------------------------------------------------------------------- |
| `model`      | Required. The transcription model, e.g. `openai/whisper-1`.                            |
| `audio`      | Required. A `file_id`, https URL, or data-URI to transcribe.                           |
| `language`   | ISO-639-1 hint (e.g. `en`); the provider validates it.                                 |
| `prompt`     | Context or vocabulary hint to bias the transcript.                                     |
| `diarize`    | Request speaker labels on segments. Rejected on models that don't support diarization. |
| `parameters` | Opaque per-provider passthrough.                                                       |

Transcription is billed per provider-reported audio duration. Segment and word timestamps are returned when the model provides them.

## Discover models

`GET /v3/audio/models` lists the audio models available, tagged `tts` or `stt`, with their voices and formats. Each model's `params.tts` / `params.stt` block also carries a `parameters` list of the native passthrough keys it accepts (e.g. ElevenLabs' exact `output_format` preset, or a `language_code`), so you can discover the model-specific knobs for `parameters` rather than guessing:

```bash theme={null}
# all audio models, or filter by type
curl -s "https://api.opper.ai/v3/audio/models?type=tts" \
  -H "Authorization: Bearer $OPPER_API_KEY"
```

## What's next

<CardGroup cols={2}>
  <Card title="Realtime voice" icon="microphone" href="/build/realtime/quickstart">
    Live, two-way voice over WebSocket.
  </Card>

  <Card title="Models" icon="brain" href="/capabilities/models">
    Which models do speech and transcription.
  </Card>

  <Card title="Control Plane" icon="shield-check" href="/control-plane/overview">
    Govern providers, regions, and spend on every call.
  </Card>

  <Card title="Video" icon="film" href="/build/multimodal/video">
    Generate video from a prompt or image.
  </Card>
</CardGroup>
