Преобразование речи в текст
Расшифровывайте аудио в текст через выделенный эндпоинт RouterAI API.
RouterAI поддерживает преобразование речи в текст (STT, speech-to-text) через выделенный эндпоинт /api/v1/audio/transcriptions. Эндпоинт принимает запрос в двух форматах — на выбор:
- multipart/form-data (OpenAI-совместимый): аудиофайл в поле
file, как в официальном OpenAI SDK (client.audio.transcriptions.create) иcurl -F - JSON: аудио в кодировке base64 в поле
input_audio
В ответ придёт JSON с распознанным текстом и статистикой использования. Оба формата делят общий лимит тела запроса 32 МБ.
Примечание: В JSON-формате аудио передаётся как строка base64 (сырые байты, не data URI). Расшифровку выполняют только модели с поддержкой транскрибации.
Поиск моделей
Модели с поддержкой STT можно найти на нашей странице моделей, отфильтровав по модальности аудио. Примеры моделей: openai/whisper-large-v3, openai/whisper-1.
OpenAI SDK и multipart/form-data
Эндпоинт совместим с официальным OpenAI SDK — достаточно указать base_url:
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://routerai.ru/api/v1",
)
with open("audio.mp3", "rb") as f:
transcription = client.audio.transcriptions.create(
model="openai/whisper-large-v3",
file=f,
language="ru",
)
print(transcription.text)
import fs from 'fs';
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'YOUR_API_KEY',
baseURL: 'https://routerai.ru/api/v1',
});
const transcription = await client.audio.transcriptions.create({
model: 'openai/whisper-large-v3',
file: fs.createReadStream('audio.mp3'),
language: 'ru',
});
console.log(transcription.text);
То же самое через curl (заголовок Content-Type руками не ставьте — его с boundary сформирует сам curl):
curl -X POST https://routerai.ru/api/v1/audio/transcriptions \
-H "Authorization: Bearer $ROUTERAI_API_KEY" \
-F "file=@audio.mp3" \
-F "model=openai/whisper-large-v3" \
-F "language=ru"
Формат аудио определяется по расширению имени файла, фолбэк — Content-Type части file. Если расширение нераспознано (например, файл называется blob), переименуйте файл или передайте у части корректный MIME-тип (audio/mpeg, audio/wav, …). Поле stream игнорируется — эндпоинт нестриминговый. Лимит размера файла — 25 МБ. Объект provider (маршрутизация и параметры провайдера, см. ниже) в multipart передаётся либо одним полем provider со строкой JSON, либо полями вида provider[options][azure][diarization][enabled]=true — именно так OpenAI SDK сериализует extra_body.
Использование API (JSON)
Отправьте POST запрос на /api/v1/audio/transcriptions с JSON-телом, содержащим аудио в base64. В ответ придёт JSON с распознанным текстом и статистикой использования.
Структура запроса
model— идентификатор STT-модели (например,openai/whisper-large-v3)input_audio.data— содержимое аудиофайла в кодировке base64input_audio.format— формат файла (mp3,wav,flac,m4a,ogg,webm,aac)
Пример запроса cURL
# Кодируем аудиофайл в base64
BASE64_AUDIO=$(base64 -w 0 ./audio.wav)
curl -X POST https://routerai.ru/api/v1/audio/transcriptions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ROUTERAI_API_KEY" \
-d @- << EOF
{
"model": "openai/whisper-large-v3",
"input_audio": {
"data": "$BASE64_AUDIO",
"format": "wav"
}
}
EOF
Пример на Python
import requests
import base64
with open("audio.wav", "rb") as f:
base64_audio = base64.b64encode(f.read()).decode("utf-8")
response = requests.post(
url="https://routerai.ru/api/v1/audio/transcriptions",
headers={
"Authorization": "Bearer $ROUTERAI_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "openai/whisper-large-v3",
"input_audio": {
"data": base64_audio,
"format": "wav",
},
},
)
result = response.json()
print(result["text"])
Пример на TypeScript (fetch)
import fs from 'fs';
const audioBuffer = await fs.promises.readFile('audio.wav');
const base64Audio = audioBuffer.toString('base64');
const response = await fetch('https://routerai.ru/api/v1/audio/transcriptions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ROUTERAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/whisper-large-v3',
input_audio: {
data: base64Audio,
format: 'wav',
},
}),
});
const result = await response.json();
console.log(result.text);
Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
model |
string | Да | STT-модель для запроса (например, openai/whisper-large-v3) |
input_audio |
object | Да (JSON) | Аудио для расшифровки (только JSON-формат) |
input_audio.data |
string | Да (JSON) | Аудио в кодировке base64 (сырые байты, не data URI) |
input_audio.format |
string | Да (JSON) | Формат аудио (mp3, wav, flac, m4a, ogg, webm, aac) |
file |
file | Да (multipart) | Аудиофайл (только multipart/form-data); формат — по расширению или MIME-типу части |
language |
string | Нет | Язык в формате ISO-639-1 (например, "ru", "en"). По умолчанию определяется автоматически |
temperature |
number | Нет | Температура семплирования. Меньшие значения дают более детерминированный результат |
response_format |
string | Нет | json (по умолчанию) — {text, usage}; verbose_json — дополнительно task, language, duration и таймстампы (см. ниже) |
timestamp_granularities |
array | Нет | word и/или segment — гранулярность таймстампов, только с response_format=verbose_json (в multipart — повторяющееся поле timestamp_granularities[]) |
provider |
object | Нет | Маршрутизация (order, only, ignore) и параметры конкретного провайдера в provider.options — например диаризация. В multipart — поле provider со строкой JSON или поля provider[...] (см. ниже) |
Формат ответа
Эндпоинт возвращает JSON-ответ с распознанным текстом:
{
"text": "Привет, это тест преобразования речи в текст.",
"usage": {
"seconds": 9.2,
"total_tokens": 113,
"input_tokens": 83,
"output_tokens": 30,
"cost": 0.19
}
}
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
text |
string | Распознанный текст |
usage.seconds |
number | Длительность входного аудио в секундах |
usage.total_tokens |
number | Всего использовано токенов (вход + выход) |
usage.input_tokens |
number | Количество тарифицированных входных токенов |
usage.output_tokens |
number | Количество сгенерированных выходных токенов |
usage.cost |
number | Стоимость запроса в рублях (тарификация RouterAI) |
Та же стоимость доступна и постфактум через GET /api/v1/generation?id=<X-Generation-Id> (поле total_cost, в рублях) — идентификатор генерации приходит в заголовке ответа X-Generation-Id.
Подробный ответ (verbose_json)
С response_format: "verbose_json" ответ дополнительно содержит метаданные расшифровки и таймстампы:
{
"text": "Привет, это тест преобразования речи в текст.",
"task": "transcribe",
"language": "russian",
"duration": 9.2,
"segments": [
{
"id": 0,
"start": 0.0,
"end": 4.5,
"text": "Привет, это тест",
"avg_logprob": -0.21,
"no_speech_prob": 0.01
}
],
"words": [
{ "word": "Привет", "start": 0.0, "end": 0.6 }
],
"usage": { "seconds": 9.2, "cost": 0.19 }
}
| Поле | Тип | Описание |
|---|---|---|
task |
string | Выполненная задача (transcribe) |
language |
string | Определённый или заданный язык аудио |
duration |
number | Длительность входного аудио в секундах |
segments |
array | Посегментные таймстампы (с timestamp_granularities: ["segment"]) |
words |
array | Пословные таймстампы (с timestamp_granularities: ["word"]), если провайдер их возвращает |
Примечание: verbose_json и таймстампы поддерживаются не всеми моделями и провайдерами.
Дополнительные параметры провайдера
У STT-моделей есть возможности, которых нет в общем контракте эндпоинта: разделение собеседников, подсказки словаря, пунктуация и т.п. Они включаются параметрами в родных именах провайдера через объект provider.options:
"provider": {
"options": {
"<slug провайдера>": { "<параметр>": "<значение>" }
}
}
Как это работает:
- Ключ — slug провайдера, который обслуживает модель:
azure,xai,deepgram,groq, … Его видно в карточке модели на странице моделей, в полеtagсписка endpoint’ов модели и в полеmeta.providerответа. - Передаются только опции того провайдера, который реально выполнил запрос. Если у модели несколько провайдеров, можно перечислить опции для каждого или закрепить провайдера через
provider.order/provider.only. - Неизвестные параметры провайдер молча отбрасывает. Отсутствие ошибки не означает, что параметр применился — проверяйте результат.
- Значения передаются как есть: булевы, числа, строки, вложенные объекты — в том виде, какой ожидает провайдер.
Здесь же работают параметры маршрутизации provider.order, provider.only, provider.ignore — как и в остальных эндпоинтах.
Как передать
Один и тот же объект provider можно отправить тремя способами. Ниже — на примере диаризации у microsoft/mai-transcribe-2.
JSON-запрос — объект целиком в теле:
{
"model": "microsoft/mai-transcribe-2",
"response_format": "verbose_json",
"input_audio": { "data": "<base64>", "format": "wav" },
"provider": {
"options": {
"azure": { "diarization": { "enabled": true } }
}
}
}
OpenAI SDK — через extra_body (Python) или дополнительное поле запроса (TypeScript). SDK сам разложит объект в поля формы provider[options][azure][diarization][enabled]=true:
with open("audio.wav", "rb") as f:
transcription = client.audio.transcriptions.create(
model="microsoft/mai-transcribe-2",
file=f,
response_format="verbose_json",
extra_body={
"provider": {
"options": {"azure": {"diarization": {"enabled": True}}}
}
},
)
for segment in transcription.segments:
print(segment["speaker"], segment["text"])
const transcription = await client.audio.transcriptions.create({
model: 'microsoft/mai-transcribe-2',
file: fs.createReadStream('audio.wav'),
response_format: 'verbose_json',
// @ts-expect-error — поле вне типов SDK, уходит в тело как есть
provider: { options: { azure: { diarization: { enabled: true } } } },
});
curl с multipart — объект одной JSON-строкой:
curl -X POST https://routerai.ru/api/v1/audio/transcriptions \
-H "Authorization: Bearer $ROUTERAI_API_KEY" \
-F "file=@audio.wav" \
-F "model=microsoft/mai-transcribe-2" \
-F "response_format=verbose_json" \
-F 'provider={"options":{"azure":{"diarization":{"enabled":true}}}}'
Поля вида provider[...] тоже принимаются напрямую (-F 'provider[options][azure][diarization][enabled]=true', массивы — повтором поля provider[order][]=azure). Строковые значения таких полей приводятся к типам: true/false становятся булевыми, числа — числами, остальное остаётся строками. Если провайдеру нужна строка, похожая на число, передайте provider одной JSON-строкой.
Диаризация (разделение собеседников)
Диаризация — это метка спикера у каждого фрагмента расшифровки. Она включается параметром провайдера через provider.options и требует response_format: "verbose_json": в обычном json ответ содержит только сплошной текст, и меткам негде появиться. Верхнеуровневое поле diarize в запросе не действует.
Параметр зависит от провайдера:
| Модель | Провайдер | Параметр | Где метка speaker |
|---|---|---|---|
microsoft/mai-transcribe-2 |
azure |
"azure": { "diarization": { "enabled": true } } |
segments[] |
x-ai/grok-stt-1.0 |
xai |
"xai": { "diarize": true } |
words[] |
Запрос для x-ai/grok-stt-1.0:
{
"model": "x-ai/grok-stt-1.0",
"response_format": "verbose_json",
"input_audio": { "data": "<base64>", "format": "wav" },
"provider": {
"options": {
"xai": { "diarize": true }
}
}
}
Ответ microsoft/mai-transcribe-2 — спикеры на сегментах:
{
"text": "Добрый день, вы дозвонились в службу поддержки.\nЗдравствуйте, у меня вопрос по заказу.",
"language": "ru",
"duration": 9.16,
"segments": [
{ "id": 0, "start": 0.32, "end": 4.0, "text": "Добрый день, вы дозвонились в службу поддержки.", "speaker": 0 },
{ "id": 1, "start": 4.6, "end": 8.839, "text": "Здравствуйте, у меня вопрос по заказу.", "speaker": 1 }
],
"usage": { "seconds": 10, "cost": 0.11 }
}
Ответ x-ai/grok-stt-1.0 — спикеры на словах:
{
"text": "Добрый день, вы дозвонились в службу поддержки. Здравствуйте, у меня вопрос по заказу.",
"language": "ru",
"duration": 9.16,
"segments": [ { "id": 0, "start": 0, "end": 9.16, "text": "Добрый день, вы дозвонились ..." } ],
"words": [
{ "word": "Добрый", "start": 0.281, "end": 0.702, "speaker": 0 },
{ "word": "день,", "start": 0.742, "end": 1.063, "speaker": 0 },
{ "word": "Здравствуйте,", "start": 4.57, "end": 5.231, "speaker": 1 },
{ "word": "у", "start": 5.311, "end": 5.372, "speaker": 1 }
],
"usage": { "seconds": 9.16, "cost": 0.03 }
}
speaker — порядковый индекс собеседника в рамках одного ответа (0, 1, 2, …), на каком уровне он появится — сегментов, слов или обоих — определяет провайдер. Диаризацию поддерживают не все модели: например, microsoft/mai-transcribe-1.5 на такой запрос вернёт ошибку провайдера, используйте microsoft/mai-transcribe-2.
Заголовки ответа
| Заголовок | Описание |
|---|---|
X-Generation-Id |
Уникальный ID генерации для запроса — полезен для отслеживания и отладки |
Поддерживаемые форматы аудио
Поддерживаемые форматы зависят от провайдера. Распространённые форматы:
| Формат | MIME-тип | Описание |
|---|---|---|
wav |
audio/wav |
Несжатое аудио, наивысшее качество |
mp3 |
audio/mpeg |
Сжатое аудио, широкая совместимость |
flac |
audio/flac |
Сжатие без потерь |
m4a |
audio/mp4 |
Аудио MPEG-4 |
ogg |
audio/ogg |
Аудио Ogg Vorbis |
webm |
audio/webm |
Аудио WebM, частое для записей в браузере |
aac |
audio/aac |
Advanced Audio Coding |
Примечание: Проверьте документацию вашей модели, чтобы подтвердить поддерживаемые форматы. Не все модели поддерживают все форматы.
Тарификация
STT-модели используют разные схемы тарификации в зависимости от провайдера:
- По длительности (например, OpenAI Whisper): оплата за секунду входного аудио
- По токенам (например, новые модели OpenAI): оплата за входные/выходные токены, как у текстовых моделей
Стоимость каждой модели можно посмотреть на странице моделей. Фактическая стоимость выполненного запроса (в рублях) возвращается в поле usage.cost ответа, а также доступна через GET /api/v1/generation?id=<X-Generation-Id> — поле total_cost.
Отличия от аудио входных данных
RouterAI предлагает два способа обработки аудио:
-
Преобразование речи в текст (эта страница): выделенный эндпоинт
/api/v1/audio/transcriptions, оптимизированный под транскрибацию. Возвращает структурированный JSON с текстом и статистикой использования. Лучший выбор для перевода аудио в текст. -
Аудио во входных данных чата (Аудио входные данные): аудио передаётся в составе запроса
/api/v1/chat/completionsчерез тип контентаinput_audio. Модель обрабатывает аудио вместе с текстом и отвечает в диалоговом формате. Лучший выбор для анализа аудио, ответов на вопросы по содержанию и комбинирования модальностей.
Лучшие практики
- Выбор формата: WAV даёт лучшее качество для транскрибации. MP3 и другие сжатые форматы работают хорошо, но могут немного снижать точность на пограничном аудио
- Размер файла: Очень длинные записи разбивайте на сегменты покороче. Максимальный размер тела запроса — 32 МБ
- Кодирование base64: Аудио передаётся как строка base64 (сырые байты, не data URI). В большинстве языков есть встроенные средства base64-кодирования
- Указание языка: Если язык известен заранее, передайте
languageв формате ISO-639-1 — это повышает точность и скорость
Устранение неполадок
Пустая или неверная расшифровка?
- Убедитесь, что формат аудио совпадает с полем
formatв запросе - Проверьте, что качество аудио достаточно для распознавания
- При необходимости укажите параметр
language
Запрос завершается с ошибкой размера?
- Тело запроса не должно превышать 32 МБ. Разбейте длинные записи на сегменты покороче
- Сжатые форматы (MP3, AAC) дают меньший размер и передаются быстрее
Модель не найдена?
- Найдите доступные STT-модели на странице моделей
- Проверьте корректность идентификатора модели (например,
openai/whisper-large-v3, а неwhisper-large-v3)
Ошибка аутентификации?
- Убедитесь, что используете действительный API-ключ из вашего дашборда
- Эндпоинт STT использует ту же аутентификацию, что и Chat Completions API