Когда транскрибация даёт сбой, многие сначала меняют модель или сомневаются в качестве распознавания, хотя большинство проблем возникает на четырёх уровнях: файл, аутентификация, сеть и лимиты. Интерфейс транскрибации принимает загрузку multipart/form-data, поэтому цепочка длиннее, чем у текстового API, и порядок диагностики тоже длиннее: сначала HTTP-статус и тип ошибки, затем сам запрос, и только потом аудио и промпт.
Ниже разбираем 401, ошибку формата 400, слишком большой файл 413, лимиты 429, тайм-ауты, а также пустой текст и «мусор» в ответе; даём путь диагностики и переиспользуемый код обработки. Ограничения файлов, имена моделей и формат ошибок могут меняться; ориентируйтесь на официальную документацию и материалы на сайте, а цены — на страницу тарифов.
Примечание: OpenAI и Whisper — товарные знаки соответствующих правообладателей; статья носит технический характер. Ограничения интерфейса, поддерживаемые форматы и имена моделей могут меняться; ориентируйтесь на официальную документацию и материалы на сайте.
1. Сначала выстройте порядок диагностики
| Симптом | Частый статус | Частая причина | Направление действий |
|---|---|---|---|
| Ошибка аутентификации | 401, 403 | Неверный ключ, нет Bearer, нет прав на аудио | Исправить учётные данные, не повторять |
| Формат не поддерживается | 400 | Кодек не в списке, расширение не совпадает с кодировкой | Перекодировать и отправить снова |
| Файл слишком большой | 413 или 400 | Превышен лимит на файл | Сжать или нарезать |
| Слишком частые запросы | 429 | Превышены запросы в минуту, параллелизм или квота | Задержка, очередь, разделение ключей |
| Ошибка сервера | 500, 502, 503 | Сбой или перегрузка upstream | Задержка и ограниченные повторы |
| Тайм-аут | Нет ответа или обрыв | Большой файл, медленная загрузка, долгая обработка | Нарезка, настройка тайм-аутов |
| Пустой текст | 200 | Тишина, низкая громкость, неверный язык, проблема кодирования | Проверять аудио, а не повторять |
Если в заголовках ответа или теле ошибки есть request-id, обязательно сохраните его. Для поддержки один request ID и минимальное воспроизводимое аудио полезнее десяти скриншотов.
2. 401: сначала заголовок, потом ключ
401 означает, что аутентификация не прошла, и обычно не связана с балансом или возможностями модели. Проверяйте по порядку:
- Заголовок имеет вид
Authorization: Bearer <key>, не потеряны лиBearerи пробел. - Нет ли пробелов, переносов строк или кавычек до и после ключа. Это частая проблема при копировании из чата.
- Действительно ли загружены переменные окружения. Можно вывести только префикс, но не пишите полный ключ в журнал.
- Не отозван ли ключ, относится ли он к текущему проекту, есть ли у аккаунта права на аудио.
- Правильный ли base URL —
https://ai.zhongshangqihang.com/v1, и путь —/v1/audio/transcriptions. - Если это шлюз, уточните, открыта ли на этом входе аудиотранскрибация: не предполагайте, что при работающем текстовом интерфейсе аудио тоже доступно.
Ещё одна частая ошибка — положить файл в JSON-тело. Интерфейс транскрибации требует multipart/form-data; в командной строке используйте curl -F "file=@meeting.mp3", а не -d. При неверном формате тела иногда возвращается 400, а иногда 401, если валидные учётные данные не были прочитаны.
3. 400 и 413: формат и размер
В 400 чаще всего виноват неподдерживаемый формат. В официальной документации перечислены mp3, mp4, mpeg, mpga, m4a, wav, webm и другие; полный список и требования к кодировке смотрите в актуальной документации. Переименование расширения не заменяет перекодирование: если переименовать .amr в .mp3, сервер прочитает исходный кодек и всё равно вернёт ошибку.
413 обычно означает превышение лимита на файл. Часто упоминается лимит 25 МБ, точное значение смотрите в документации. Есть два способа:
- Сжатие: привести к 16 кГц моно; для речи высокий битрейт не нужен. Подойдёт
ffmpeg -i input.mp3 -ac 1 -ar 16000 -b:a 64k output.mp3. - Нарезка: резать по 10 минут, транскрибировать по частям и собирать. Точки реза выбирайте по тишине, оставляйте небольшое перекрытие, чтобы не разрывать слова.
Не пытайтесь «впихнуть» длинное аудио только сжатием. Чем больше файл, тем медленнее загрузка, выше риск тайм-аута и дороже повтор после сбоя. Параллельная нарезка стабильнее, но контролируйте параллелизм, иначе 413 превратится в 429.
4. 429: лимит — это не всегда нехватка баланса
429 означает превышение лимита частоты, параллелизма или квоты. При одном и том же статусе тип ошибки может отличаться: иногда это превышение частоты, иногда недостаточная квота. Сначала посмотрите тип, затем решайте: ждать, снижать параллелизм или пополнять баланс.
Типичные причины: слишком много параллельных пакетных задач; несколько сервисов используют один ключ; немедленный повтор после сбоя превращается в шторм повторов; длинное аудио надолго занимает соединение; у бесплатного или младшего тарифа небольшая квота в минуту.
Порядок действий: проверьте Retry-After в ответе, затем повторяйте с экспоненциальной задержкой и случайным разбросом; ставьте пакетные задачи в очередь и ограничивайте число одновременных запросов; разделяйте ключи по проектам; задайте предел повторов и оповещение, не допускайте бесконечного цикла. Транскрибация тарифицируется по длительности, повторная отправка может привести к двойному списанию, поэтому до повтора убедитесь, что предыдущий запрос не завершился успешно.
5. Тайм-ауты: медленная загрузка или долгая обработка
Тайм-аут может произойти на трёх этапах: установка соединения, загрузка файла, обработка на сервере. Если тайм-аут случается и на маленьких файлах, проверяйте сеть, прокси и base URL; если стабильно на больших — нарезайте и сжимайте.
Клиент должен явно задавать тайм-аут, не полагаясь на значения по умолчанию. Время транскрибации зависит от длительности, размера файла и очереди; задайте достаточно щедрый, но конечный лимит, например две–три минуты, и по журналу задач различайте «отправлено, но не вернулось» и «вообще не ушло». С автоматическим повтором после тайм-аута будьте осторожны: если сервер уже завершил обработку, повтор даст второе списание и дубликат результата.
6. 200, но пустой текст или мусор
В этих случаях HTTP-ошибки нет, и направления диагностики совершенно разные.
Пустой текст обычно означает: полная тишина или слишком низкая громкость; параметр языка не соответствует аудио; проблемы с каналами, основной канал пуст; файл загружается, но декодируется некорректно. Сначала проверьте громкость, явно передайте language=ru, затем приведите аудио к 16 кГц моно и попробуйте снова.
Мусор или большое число ошибок обычно означает: неверно определён язык, сильный диалектный акцент, музыка и голос смешаны, несколько человек перебивают друг друга, микрофон слишком далеко. Можно передать в prompt имена, названия продуктов и термины, а после транскрибации заменить по словарю. Если само аудио непригодно, смена модели не поможет — возвращайтесь к записи и предобработке.
7. Повторы и нарезка: переиспользуемый код
Повторы подходят только для временных ошибок. Для 401, 400 и 413 нужно менять запрос; слепой повтор только усугубляет проблему.
import os
import random
import time
from openai import (
OpenAI,
APIConnectionError,
APIStatusError,
APITimeoutError,
RateLimitError,
)
client = OpenAI(
api_key=os.environ["WHISPER_API_KEY"],
base_url="https://ai.zhongshangqihang.com/v1",
timeout=180,
)
def transcribe(path: str, model: str = "whisper-1", retries: int = 4) -> str:
for attempt in range(retries):
try:
with open(path, "rb") as f:
result = client.audio.transcriptions.create(
model=model,
file=f,
language="ru",
response_format="verbose_json",
)
text = (result.text or "").strip()
if not text:
raise ValueError("Пустая транскрибация: проверьте громкость, язык и каналы")
return text
except RateLimitError:
wait = min(2 ** attempt, 30) + random.random()
print(f"429, повтор через {wait:.1f} с")
time.sleep(wait)
except (APITimeoutError, APIConnectionError):
time.sleep(min(2 ** attempt, 30) + random.random())
except APIStatusError as exc:
if exc.status_code >= 500:
time.sleep(min(2 ** attempt, 30) + random.random())
else:
raise # 400/401/413 требуют исправить запрос, а не повторять
raise RuntimeError("Лимит повторов исчерпан")
print(transcribe("meeting.mp3"))
Имена моделей смотрите в документации на сайте; whisper-1 — лишь распространённый пример. Аудио сверх лимита сначала нарежьте через ffmpeg, затем вызывайте эту функцию для каждого фрагмента и при сборке не забудьте прибавить начальное время каждого фрагмента.
8. Журналы и список для обращения в поддержку
- Зафиксируйте время, часовой пояс, HTTP-статус и тип ошибки.
- Сохраните
request-idи укажите, шёл запрос на официальный вход или через шлюз. - Запишите имя файла, фактический кодек, длительность, размер, частоту дискретизации и число каналов.
- Запишите ключевые параметры:
model,language,response_format. - Зафиксируйте число повторов, время ожидания и итоговый результат.
- Отметьте, был ли ключ общим, каковы были параллелизм и масштаб пакетной задачи.
- Подготовьте минимальное воспроизводимое аудио на 10–30 секунд без персональных данных.
При обращении в поддержку не отправляйте полный ключ и не передавайте записи клиентов без разрешения. Минимальный стабильно воспроизводимый пример полезнее описания «иногда выдаёт ошибку».
Частые вопросы
413 и 400 — обе про файл. Как различить?
413 обычно означает превышение размера: помогает сжатие или нарезка. 400 чаще связан с форматом, параметрами или кодировкой: нужны перекодирование и проверка полей. Смотрите тип и сообщение, а не только статус.
Что делать, если 429 не проходит?
Сначала определите, превышение частоты это или нехватка квоты. При частоте снижайте параллелизм, ставьте в очередь и разделяйте ключи; при квоте нужно пополнение или другой вход. При постоянном 429 не наращивайте повторы — это только удлинит восстановление.
Стоит ли сразу повторять при тайм-ауте?
Сначала оцените, мог ли запрос уже завершиться на сервере. Транскрибация могла быть списана, и прямой повтор даст дубликат и вторую оплату. Проверьте состояние по журналу задач или идемпотентному дизайну, затем решайте.
Пустая транскрибация — модель сломалась?
Чаще нет. Проверьте громкость, участки тишины, параметр языка, каналы и фактический кодек. Тот же файл через другой вход поможет быстро понять, проблема в аудио или в сервисе.
Как отличить ошибку шлюза от ошибки официального API?
Сохраните request-id и тип ошибки и отправьте один и тот же запрос на оба входа. Если официальный вход работает, а шлюз выдаёт ошибку, проблема скорее в конфигурации или пересылке; если ошибка на обоих — проверяйте ключ, сеть и файл.
Следующий шаг
Начните с регистрации в ZSQH AI Gateway, отработайте на минутном аудио 401, 413, 429 и тайм-аут по одному разу, затем подключайте production-мониторинг. Доступность моделей и цены — на странице цен на модели.
Что читать дальше:
