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

# Text to speech

> Turn text into an audio file with POST /v1/audio/speech and save the result as MP3, WAV or another format.

Send text, a model and a voice to `POST /v1/audio/speech`, and NagaAI answers with the audio file itself. The endpoint follows the OpenAI Audio format, so the OpenAI SDK works unchanged. Choose a model whose `operations` include `speech` in [`GET /v1/models`](https://docs.naga.ac/get-started/models). Several families serve speech, for example `eleven-v3`, `eleven-multilingual-v2` and the Gemini TTS models, and the examples below use `eleven-v3`.

## Generate speech

```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])

with client.audio.speech.with_streaming_response.create(
    model="eleven-v3",
    voice="alloy",
    input="Your order has shipped and will arrive on Thursday.",
) as response:
    response.stream_to_file("speech.mp3")

print("Saved speech.mp3")
```

```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });

const response = await client.audio.speech.create({
  model: "eleven-v3",
  voice: "alloy",
  input: "Your order has shipped and will arrive on Thursday.",
});

fs.writeFileSync("speech.mp3", Buffer.from(await response.arrayBuffer()));
console.log("Saved speech.mp3");
```

```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
curl https://api.naga.ac/v1/audio/speech \
  -H "Authorization: Bearer $NAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "eleven-v3", "voice": "alloy", "input": "Your order has shipped and will arrive on Thursday."}' \
  --output speech.mp3
```

The body of the response is the audio file, not JSON, and its `Content-Type` header names the format. [Listen to a sample](https://docs.naga.ac/examples/speech.mp3).

## Choose a voice

Each model has its own voices, and `voice` is required. OpenAI voice names such as `alloy` and `nova` also work on ElevenLabs, Voxtral and Gemini TTS models, where NagaAI maps them to similar voices. If you want a specific voice on one of those models, use the name that model documents.

`instructions` gives style directions such as pace or mood, on models that support them. `speed` is a multiplier of the model's normal pace and must be greater than 0.

## Choose a format

`response_format` is `mp3` (default), `opus`, `aac`, `flac`, `wav` or `pcm`. Not every model produces every format, and a format the model cannot produce fails with `400`:

| Models | Formats |
| - | - |
| ElevenLabs | No `aac` or `flac` |
| Gemini TTS | `wav` and `pcm` only, with `wav` as the default |
| A model with no choice of format | Its own format, named in the `Content-Type` of the response |

`pcm` is raw 24 kHz, 16-bit signed little-endian mono samples with no header, so wrap it in a WAV container before you play it.

## Know the limits

`input` takes up to 32,768 characters. For longer text, split it at sentence boundaries and join the audio files.

Each model's `pricing` in `GET /v1/models` says what NagaAI counts for it. See [Models](https://docs.naga.ac/get-started/models.md) for how to read the rows.

## Troubleshooting

### 400 on `response_format`

The model cannot produce that format. Choose a format that your model produces, or omit the field to get the model's default format.

### 400 with `String should have at most 32768 characters`

The text in `input` is too long. Split it into several requests.

### 400 with `Input should be greater than 0`

`speed` must be a number above zero.

### 400 `model_not_found`

The model does not exist or has no `speech` operation. Check its `operations` in `GET /v1/models`.

### 402 `insufficient_quota`

The balance is too low for a paid model. Add credits and send the request again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.