# Синтез речи

> Синтезируйте речь из текста через выделенный эндпоинт RouterAI API.

RouterAI поддерживает синтез речи (TTS, text-to-speech) через выделенный эндпоинт `/api/v1/audio/speech`, совместимый с [OpenAI Audio Speech API](https://platform.openai.com/docs/api-reference/audio/createSpeech). Отправьте текст и получите в ответ поток сырых байтов аудио в выбранном формате.

**Примечание**: Ответ эндпоинта — **бинарный поток аудио**, а не JSON. Его можно сразу записать в файл или передать аудиоплееру.

## Поиск моделей

Модели с поддержкой TTS можно найти на нашей [странице моделей](https://routerai.ru/models?output_modalities[]=speech), отфильтровав по модальности аудио на выходе. Примеры моделей: `x-ai/grok-voice-tts-1.0`, `openai/gpt-4o-mini-tts`.

## Использование API

Отправьте `POST` запрос на [`/api/v1/audio/speech`](https://routerai.ru/docs/reference#tag/speech) с текстом, который нужно озвучить. Ответ — поток сырых байтов аудио (не JSON), поэтому его можно направить напрямую в файл.

### Структура запроса

1. `model` — идентификатор TTS-модели (например, `x-ai/grok-voice-tts-1.0`)
2. `input` — текст для синтеза речи
3. `voice` — идентификатор голоса (набор голосов зависит от модели)
4. `response_format` — формат выходного аудио (`mp3` или `pcm`)

### Пример запроса cURL

```bash
curl -X POST https://routerai.ru/api/v1/audio/speech \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ROUTERAI_API_KEY" \
  --output output.mp3 \
  -d '{
    "model": "x-ai/grok-voice-tts-1.0",
    "input": "Привет! Это пример синтеза речи.",
    "voice": "eve",
    "response_format": "mp3"
  }'
```

### Пример на Python

```python
import requests

response = requests.post(
    url="https://routerai.ru/api/v1/audio/speech",
    headers={
        "Authorization": "Bearer $ROUTERAI_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "model": "x-ai/grok-voice-tts-1.0",
        "input": "Привет! Это пример синтеза речи.",
        "voice": "eve",
        "response_format": "mp3",
    },
)
response.raise_for_status()

with open("output.mp3", "wb") as f:
    f.write(response.content)

generation_id = response.headers.get("X-Generation-Id")
print(f"Аудио сохранено. ID генерации: {generation_id}")
```

### Пример на TypeScript (fetch)

```typescript
const response = await fetch('https://routerai.ru/api/v1/audio/speech', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ROUTERAI_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'x-ai/grok-voice-tts-1.0',
    input: 'Привет! Это пример синтеза речи.',
    voice: 'eve',
    response_format: 'mp3',
  }),
});

if (!response.ok) {
  const err = await response.json();
  throw new Error(`Ошибка TTS ${response.status}: ${JSON.stringify(err)}`);
}

const audioBuffer = await response.arrayBuffer();
const generationId = response.headers.get('X-Generation-Id');
console.log(`ID генерации: ${generationId}`);
// Сохраните audioBuffer в файл или воспроизведите напрямую
```

### Параметры запроса

| Параметр          | Тип    | Обязательный | Описание                                                                                         |
| ----------------- | ------ | ------------ | ------------------------------------------------------------------------------------------------ |
| `model`           | string | Да           | TTS-модель для запроса (например, `x-ai/grok-voice-tts-1.0`)                                      |
| `input`           | string | Да           | Текст для синтеза речи                                                                            |
| `voice`           | string | Да           | Идентификатор голоса. Набор голосов зависит от модели — смотрите страницу модели на [странице моделей](https://routerai.ru/models) |
| `response_format` | string | Нет          | Формат выходного аудио: `mp3` или `pcm`                                                           |
| `speed`           | number | Нет          | Множитель скорости воспроизведения. Используется только моделями с его поддержкой (например, OpenAI TTS); остальными провайдерами игнорируется |

## Формат ответа

Эндпоинт возвращает **поток сырых байтов аудио**, а не JSON. В ответе присутствуют следующие заголовки:

| Заголовок         | Описание                                                                       |
| ----------------- | ------------------------------------------------------------------------------ |
| `Content-Type`    | MIME-тип аудио: `audio/mpeg` для формата `mp3`, `audio/pcm` для формата `pcm`    |
| `X-Generation-Id` | Уникальный ID генерации для запроса — полезен для отслеживания и отладки         |

### Форматы вывода

| Формат | Content-Type | Описание                                                                          |
| ------ | ------------ | --------------------------------------------------------------------------------- |
| `mp3`  | `audio/mpeg` | Сжатое аудио, меньший размер файла. Подходит для хранения и воспроизведения        |
| `pcm`  | `audio/pcm`  | Несжатое сырое аудио. Низкая задержка, подходит для потоковых конвейеров реального времени |

## Тарификация

TTS-модели тарифицируются **посимвольно** — за количество символов входного текста. Стоимость зависит от модели и провайдера. Стоимость за символ для каждой модели можно посмотреть на [странице моделей](https://routerai.ru/models).

## Совместимость с OpenAI SDK

Эндпоинт TTS полностью совместим с OpenAI SDK. Достаточно указать клиентским библиотекам OpenAI базовый URL RouterAI:

```python
from openai import OpenAI

client = OpenAI(
    api_key="$ROUTERAI_API_KEY",
    base_url="https://routerai.ru/api/v1",
)

# Без стриминга: получаем полный ответ с аудио
response = client.audio.speech.create(
    model="x-ai/grok-voice-tts-1.0",
    input="На дворе трава, на траве дрова.",
    voice="eve",
    response_format="mp3",
)
response.write_to_file("output.mp3")

# Стриминг: обрабатываем аудио-чанки по мере поступления
with client.audio.speech.with_streaming_response.create(
    model="x-ai/grok-voice-tts-1.0",
    input="На дворе трава, на траве дрова.",
    voice="eve",
    response_format="mp3",
) as response:
    response.stream_to_file("output.mp3")
```

```typescript
import OpenAI from 'openai';
import fs from 'fs';

const client = new OpenAI({
  apiKey: process.env.ROUTERAI_API_KEY,
  baseURL: 'https://routerai.ru/api/v1',
});

const response = await client.audio.speech.create({
  model: 'x-ai/grok-voice-tts-1.0',
  input: 'На дворе трава, на траве дрова.',
  voice: 'eve',
  response_format: 'mp3',
});

const buffer = Buffer.from(await response.arrayBuffer());
await fs.promises.writeFile('output.mp3', buffer);
console.log('Аудио сохранено в output.mp3');
```

## Лучшие практики

- **Выбор формата**: Используйте `mp3` для хранения и обычного воспроизведения. Используйте `pcm` для потоковых конвейеров реального времени, где важна задержка
- **Выбор голоса**: Разные провайдеры предлагают разные голоса. Сверьтесь с документацией модели или поэкспериментируйте с доступными голосами, чтобы подобрать подходящий под ваш сценарий
- **Длина текста**: Очень длинные тексты разбивайте на сегменты покороче и объединяйте получившееся аудио. Это повышает надёжность и снижает задержку до первого аудиофрагмента. Максимальный размер тела запроса — 32 МБ
- **Параметр скорости**: `speed` поддерживается только некоторыми провайдерами (например, OpenAI) и молча игнорируется теми, кто его не поддерживает

## Устранение неполадок

**Пустой или повреждённый аудиофайл?**

- Убедитесь, что `response_format` совпадает с тем, как вы сохраняете файл (например, не сохраняйте вывод `pcm` с расширением `.mp3`)
- Проверьте статус ответа — ответы со статусом не 200 возвращают JSON с ошибкой, а не аудио

**Модель не найдена?**

- Найдите доступные TTS-модели на [странице моделей](https://routerai.ru/models?output_modalities[]=speech)
- Проверьте корректность идентификатора модели (например, `x-ai/grok-voice-tts-1.0`, а не `grok-voice-tts`)

**Голос недоступен?**

- Набор голосов зависит от провайдера. Сверьтесь с документацией провайдера на предмет поддерживаемых идентификаторов голосов
- У каждой модели свой набор голосов — полный список смотрите на странице модели на [странице моделей](https://routerai.ru/models?output_modalities[]=speech)
