Расшифровать аудио
POST /v1/audio/transcriptions
Преобразует аудиофайл в текст через Whisper Large v3 Turbo — без подключения BYOK. Расшифровка учитывается в AI-квоте портала по длительности аудио: в рамках квоты тарифа деньги с баланса не списываются, сверх квоты расход списывается с денежного баланса портала по базовой цене модели. Принимает файл через multipart/form-data. Формат запроса и ответа совместим с POST /v1/audio/transcriptions из OpenAI API.
Ответ приходит в сыром OpenAI-формате.
Обёртки
{success, data}, которая используется в остальных эндпоинтах Вайбкод —/v1/deals,/v1/tasksи других, — здесь нет.Так сделано для совместимости с OpenAI SDK. Если у вас единый клиент с проверкой
if (!response.success), добавьте для AI Router исключение.
Поля запроса (form-data)
| Поле | Тип | Обяз. | По умолч. | Описание |
|---|---|---|---|---|
file |
file | да | — | Аудиофайл. Поддерживаются mp3, mp4, mpeg, mpga, m4a, wav, webm, flac, ogg. Максимальный размер — 25 МБ |
model |
string | нет | deepdml/faster-whisper-large-v3-turbo-ct2 |
ID Whisper-модели. Префикс bitrix/ опционален и автоматически удаляется |
language |
string | нет | автоопределение | Код языка по ISO 639 (2-3 буквы): ru, en, de, fr, zh и т. п. Указание языка ускоряет распознавание |
prompt |
string | нет | — | Контекстная подсказка: тема разговора, стиль, правильное написание терминов. До 2000 символов, модель учитывает последние ~224 токена |
hotwords |
string | нет | — | Спец-слова и термины через запятую — повышают точность распознавания редких названий и брендов. До 500 символов |
temperature |
number | нет | 0 |
Температура декодера от 0 до 1. 0 — детерминированный результат, выше — больше вариативности. Значения вне диапазона отклоняются |
vad_filter |
boolean | нет | — | true включает VAD-фильтр: модель вырезает тишину перед распознаванием — меньше галлюцинаций на записях с паузами |
timestamp_granularities[] |
string | нет | segment |
Детализация таймстампов: word или segment (поле можно повторять). Только с response_format=verbose_json. С word каждый сегмент дополняется массивом words с таймингом и вероятностью каждого слова |
response_format |
string | нет | json |
Формат результата: json, text, srt, vtt, verbose_json |
Примеры
curl — личный ключ
curl -X POST https://vibecode.bitrix24.tech/v1/audio/transcriptions \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@call-recording.mp3" \
-F "language=ru" \
-F "response_format=json"
curl — OAuth-приложение
curl -X POST https://vibecode.bitrix24.tech/v1/audio/transcriptions \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-F "file=@call-recording.mp3" \
-F "language=ru" \
-F "response_format=json"
JavaScript — личный ключ
const formData = new FormData()
formData.append('file', audioFile) // объект File или Blob
formData.append('language', 'ru')
formData.append('response_format', 'json')
const res = await fetch('https://vibecode.bitrix24.tech/v1/audio/transcriptions', {
method: 'POST',
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
body: formData,
})
const result = await res.json()
console.log('Распознанный текст:', result.text)
JavaScript — OAuth-приложение
const formData = new FormData()
formData.append('file', audioFile)
formData.append('language', 'ru')
const res = await fetch('https://vibecode.bitrix24.tech/v1/audio/transcriptions', {
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
body: formData,
})
const result = await res.json()
console.log('Текст:', result.text)
Поля ответа
Структура ответа зависит от response_format. Формат json (по умолчанию) — самый компактный, verbose_json — с таймингами.
`response_format: json`
| Поле | Тип | Описание |
|---|---|---|
text |
string | Распознанный текст целиком |
`response_format: text`
Ответ — обычная строка с распознанным текстом, без JSON-обёртки.
`response_format: verbose_json`
| Поле | Тип | Описание |
|---|---|---|
task |
string | Тип задачи: transcribe |
language |
string | Код определённого или указанного языка |
duration |
number | Длительность аудио в секундах |
text |
string | Распознанный текст целиком |
usage |
object | null | Метаданные использования модели. null, если модель их не возвращает |
words |
array | Пословные тайминги на уровне всего ответа. Пустой массив, если пословные тайминги не запрошены |
segments |
array | Сегменты с таймингами и метаданными распознавания |
segments[].id |
number | Порядковый номер сегмента |
segments[].seek |
number | Внутренний сдвиг окна распознавания Whisper |
segments[].start |
number | Начало сегмента в секундах |
segments[].end |
number | Конец сегмента в секундах |
segments[].text |
string | Текст сегмента |
segments[].tokens |
array | Токены модели для текста сегмента (целые числа) |
segments[].temperature |
number | Температура декодирования, применённая моделью |
segments[].avg_logprob |
number | Средняя логарифмическая вероятность токенов сегмента — метрика уверенности |
segments[].compression_ratio |
number | Коэффициент сжатия текста сегмента |
segments[].no_speech_prob |
number | Вероятность того, что в сегменте нет речи |
segments[].words |
array | Пословные тайминги внутри сегмента. Пустой массив, если не запрошены |
segments[].emotion |
string | null | Определённая эмоция сегмента. null, если не определена |
`response_format: srt` / `vtt`
Ответ — субтитры в формате SubRip Text или WebVTT.
Пример ответа
response_format: json:
{
"text": "Здравствуйте, ООО Вектор. Хотим CRM на 50 пользователей, бюджет до 500 тысяч в месяц."
}
response_format: verbose_json:
{
"task": "transcribe",
"language": "ru",
"duration": 8.42,
"text": "Здравствуйте, ООО Вектор. Хотим CRM на 50 пользователей, бюджет до 500 тысяч в месяц.",
"usage": null,
"words": [],
"segments": [
{
"id": 0,
"seek": 0,
"start": 0.0,
"end": 3.2,
"text": "Здравствуйте, ООО Вектор.",
"tokens": [50365, 2425, 11, 341, 307],
"temperature": 0.0,
"avg_logprob": -0.38,
"compression_ratio": 1.12,
"no_speech_prob": 0.02,
"words": [],
"emotion": null
},
{
"id": 1,
"seek": 320,
"start": 3.2,
"end": 8.42,
"text": "Хотим CRM на 50 пользователей, бюджет до 500 тысяч в месяц.",
"tokens": [50414, 1003, 13767, 295, 1500],
"temperature": 0.0,
"avg_logprob": -0.41,
"compression_ratio": 1.20,
"no_speech_prob": 0.01,
"words": [],
"emotion": null
}
]
}
Пример ответа при ошибке
400 no_file — поле file не передано:
{
"error": {
"message": "Audio file is required. Send as multipart/form-data with field \"file\".",
"type": "invalid_request_error",
"code": "no_file"
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | no_file |
Поле file не передано в multipart/form-data |
| 400 | empty_file |
Поле file передано, но файл пустой (0 байт). Частая причина: curl -F "file=path" без префикса @ — curl отправляет строку пути вместо содержимого файла |
| 400 | invalid_prompt |
Поле prompt длиннее 2000 символов |
| 400 | invalid_hotwords |
Поле hotwords длиннее 500 символов |
| 400 | invalid_temperature |
Поле temperature не число или вне диапазона 0..1 |
| 400 | invalid_vad_filter |
Поле vad_filter не true и не false |
| 400 | invalid_timestamp_granularities |
Значение не word/segment, либо формат ответа не verbose_json |
| 400 | invalid_language |
Код языка не соответствует формату ISO 639 (2-3 буквы) |
| 402 | ai_credentials_not_configured |
На платформе не настроен Bitrix-провайдер |
| 402 | insufficient_balance |
PREPAY-счёт ушёл за овердрафт — проверяется ДО вызова распознавания (только PLATFORM/PORTAL-ключи; BYOK бесплатен и не проверяется). Полностью замороженный счёт отклоняется раньше кодом ACCOUNT_FROZEN |
| 402 | ai_quota_exhausted |
Месячная AI-квота портала исчерпана — см. «Известные особенности» ниже |
| 403 | scope_missing |
API-ключу не хватает скоупа vibe:ai |
| 502 | ai_provider_unavailable |
Whisper-сервис вернул ошибку или недоступен |
| 503 | ai_provider_timeout |
Whisper не ответил в течение 15 минут — файл слишком длинный или сервис перегружен. Для записей длиннее ~30 минут разбивайте на части |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 429 | ai_congested |
Пул AI-кластера перегружен. Запрос не выполнялся, списания нет, повторите его по заголовку Retry-After. Ответ несёт заголовок X-AI-Admission: shed, а не X-RateLimit-Scope |
| 429 | ai_pacing_limited |
Превышено суточное или недельное окно равномерного расходования квоты. Это не исчерпание квоты — повторите запрос по заголовку Retry-After. Подробнее — «Равномерное расходование» |
Полный список общих ошибок API — Ошибки.
Известные особенности
Подсказки повышают точность на редких терминах. Поле prompt задаёт контекст — тему разговора, стиль, правильное написание терминов. Поле hotwords перечисляет через запятую спец-слова, на которые декодер получает повышенный приоритет. Разница на фразе «обсуждаем интеграцию NeuralDeep с Kimi и подход RAG»:
| Запрос | Результат |
|---|---|
| Без подсказок | «…интеграцию нейролдипскими и подход рак для поиска…» |
С hotwords |
«…интеграцию NeuralDeep с Kimi и подход RAG для поиска…» |
В рамках квоты — без списаний, сверх квоты — по базовой цене модели. Whisper работает на инфраструктуре Битрикс24. Расшифровка тарифицируется по длительности аудио и учитывается в месячной AI-квоте портала. Пока расход укладывается в квоту тарифа, деньги с баланса портала не списываются. Сверх квоты расход списывается с денежного баланса портала по базовой цене модели из каталога. На порталах с включённым контролем квоты запрос может вернуть 402 ai_quota_exhausted, когда месячный лимит исчерпан. Поле reason различает три случая: breaker — сработал часовой предохранитель расходов сверх квоты, wallet_empty — квота исчерпана и на балансе портала нет средств, wallet_off — расход сверх квоты для портала недоступен. Поле resetAt — момент, когда запросы снова начнут проходить, для wallet_off оно может отсутствовать.
Лимит размера — 25 МБ. Для длинных записей разбивайте файл на части до 25 МБ и склеивайте результаты на стороне клиента. Один час mp3 128 кбит/с примерно 60 МБ — придётся резать.
Тайм-аут запроса — 15 минут. Расшифровка длится примерно 5-15 % от длины аудио. Файл на 5 минут (5-7 МБ mp3) расшифровывается за 15-45 секунд. При превышении тайм-аута возвращается 503 ai_provider_timeout.