Загрузка...

Преобразование речи в текст

Расшифровывайте аудио в текст через выделенный эндпоинт RouterAI API.

RouterAI поддерживает преобразование речи в текст (STT, speech-to-text) через выделенный эндпоинт /api/v1/audio/transcriptions. Эндпоинт принимает запрос в двух форматах — на выбор:

  1. multipart/form-data (OpenAI-совместимый): аудиофайл в поле file, как в официальном OpenAI SDK (client.audio.transcriptions.create) и curl -F
  2. 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 с распознанным текстом и статистикой использования.

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

  1. model — идентификатор STT-модели (например, openai/whisper-large-v3)
  2. input_audio.data — содержимое аудиофайла в кодировке base64
  3. input_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 предлагает два способа обработки аудио:

  1. Преобразование речи в текст (эта страница): выделенный эндпоинт /api/v1/audio/transcriptions, оптимизированный под транскрибацию. Возвращает структурированный JSON с текстом и статистикой использования. Лучший выбор для перевода аудио в текст.

  2. Аудио во входных данных чата (Аудио входные данные): аудио передаётся в составе запроса /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