Cuando falla la transcripción de audio, mucha gente cambia de modelo o duda de la capacidad de reconocimiento, pero la mayoría de los fallos ocurren en cuatro capas: archivo, autenticación, red y límites de velocidad. La interfaz de transcripción sube multipart/form-data, así que la cadena es más larga que en una interfaz de texto y el orden de diagnóstico también debe serlo: primero el código de estado HTTP y el tipo de error, después la solicitud y, por último, el audio y el prompt.
Este artículo desglosa los errores 401, 400 por formato, 413 por archivo demasiado grande, 429 por límite de velocidad, tiempos de espera y respuestas con texto vacío o ilegible; incluye una ruta de diagnóstico y un bloque de código reutilizable. Los límites de archivo, los nombres de modelo y el formato de error pueden cambiar según la versión; guíate por la documentación oficial y la del sitio, y consulta los precios en precios de modelos.
Nota: OpenAI y Whisper son marcas de sus respectivos titulares; este artículo solo describe la integración técnica. Los límites de la interfaz, los formatos admitidos y los nombres de modelo pueden cambiar; guíate por la documentación oficial y la del sitio.
1. Establece primero el orden de diagnóstico
| Síntoma | Código habitual | Causa frecuente | Dirección |
|---|---|---|---|
| Fallo de autenticación | 401, 403 | Clave incorrecta, falta Bearer, sin permiso para la interfaz de audio | Corregir credenciales; no reintentar |
| Formato no admitido | 400 | Codificación fuera de la lista admitida, extensión que no coincide con la codificación real | Transcodificar y reenviar |
| Archivo demasiado grande | 413 o 400 | Supera el límite por archivo | Comprimir o dividir |
| Demasiadas solicitudes | 429 | Se superó la frecuencia por minuto, la concurrencia o la cuota | Esperar, usar cola, separar claves |
| Error del servidor | 500, 502, 503 | Anomalía o sobrecarga upstream | Esperar y reintentar un número limitado de veces |
| Tiempo de espera | Sin respuesta o conexión interrumpida | Archivo grande, subida lenta, procesamiento largo | Dividir, ajustar tiempos de espera |
| Texto vacío | 200 | Silencio, volumen bajo, idioma mal detectado, codificación anómala | Revisar el audio, no reintentar |
Si la cabecera de respuesta o el cuerpo del error incluyen request-id, consérvalo. Para pedir ayuda al proveedor, un ID de solicitud y un audio mínimo reproducible valen más que diez capturas de pantalla.
2. 401: revisa primero las cabeceras y luego la clave
Un 401 indica que la autenticación no pasó y normalmente no tiene relación con el saldo ni con la capacidad del modelo. Diagnostica en este orden:
- La cabecera de autenticación debe ser
Authorization: Bearer <key>; no omitasBearerni el espacio. - Revisa espacios, saltos de línea o comillas antes y después de la clave. Es lo más habitual al copiar desde una ventana de chat.
- Confirma que la variable de entorno se carga de verdad. Puedes imprimir solo el prefijo; no escribas la clave completa en los logs.
- Comprueba si la clave fue revocada, si pertenece al proyecto actual y si la cuenta tiene permiso para la interfaz de audio.
- La URL base debe ser
https://ai.zhongshangqihang.com/v1y la ruta/v1/audio/transcriptions. - Si usas una puerta de enlace, confirma si esa entrada tiene habilitada la transcripción de audio; no des por hecho que, porque la interfaz de texto funcione, la de audio también lo hará.
Otro error común: meter el archivo en un cuerpo JSON. La interfaz de transcripción exige multipart/form-data; en la línea de comandos usa curl -F "file=@reunion.mp3", no -d. Un cuerpo con formato incorrecto a veces aparece como 400 y a veces como 401 porque no se leyó una credencial válida.
3. 400 y 413: formato y tamaño
En los 400, lo más común es un formato no admitido. La documentación oficial enumera formatos habituales como mp3, mp4, mpeg, mpga, m4a, wav y webm; la lista completa y los requisitos de codificación dependen de la documentación vigente. Cambiar la extensión no equivale a transcodificar: si renombras .amr a .mp3, el servidor seguirá leyendo la codificación original y devolverá error.
Un 413 suele indicar que el archivo supera el límite por archivo. El límite oficial habitual es 25 MB; consulta la documentación. Hay dos formas de tratarlo:
- Comprimir: convertir todo a 16 kHz mono; en voz no hace falta un bitrate alto. Puedes usar
ffmpeg -i input.mp3 -ac 1 -ar 16000 -b:a 64k output.mp3. - Dividir: cortar en tramos de 10 minutos, transcribir cada uno y unir. Elige puntos de silencio y deja un pequeño solapamiento para no partir palabras por la mitad.
No fuerces audios largos solo con compresión. Cuanto más grande es el archivo, más lenta es la subida, mayor es la probabilidad de tiempo de espera y más cuesta reenviarlo si falla. Dividir en paralelo es más estable, pero hay que controlar la concurrencia; de lo contrario, pasarás de 413 a 429.
4. 429: límite de velocidad no es lo mismo que saldo insuficiente
Un 429 indica que se superó el límite de velocidad, concurrencia o cuota. Aunque sea el mismo código, el tipo del cuerpo del error puede variar: algunos indican frecuencia excedida y otros cuota insuficiente. Mira primero el tipo de error y luego decide si esperar, reducir la concurrencia o recargar.
Escenarios habituales: demasiada concurrencia en tareas por lotes; varias aplicaciones compartiendo una clave; reintentos inmediatos tras un fallo que generan una tormenta; audios largos que ocupan la conexión demasiado tiempo; cuotas por minuto pequeñas en cuentas gratuitas o de gama baja.
Orden de tratamiento: revisa si la respuesta incluye Retry-After y reintenta con retroceso exponencial y jitter; pasa las tareas por lotes a una cola y limita las solicitudes simultáneas; separa claves por proyecto para que no compitan; fija un máximo de reintentos y alertas, sin bucles infinitos. La transcripción se factura por duración de audio, y reenviar puede duplicar el cobro; antes de reintentar, confirma si el intento anterior ya tuvo éxito.
5. Tiempos de espera: distingue subida lenta y procesamiento lento
El tiempo de espera puede ocurrir en tres fases: establecimiento de conexión, subida del archivo y procesamiento en el servidor. Si falla incluso con archivos pequeños, revisa primero la red, el proxy y la URL base; si falla de forma estable con archivos grandes, prioriza dividir y comprimir.
El cliente debe fijar el tiempo de espera explícitamente; no dependas del valor por defecto. La duración de la transcripción depende del audio, el tamaño, la cola, etc. Pon un límite holgado pero finito, por ejemplo dos o tres minutos, y usa un registro de tareas para distinguir "enviado sin respuesta" de "no llegó a enviarse". El reintento automático tras un tiempo de espera debe ser prudente: si el servidor ya terminó, el reintento genera un segundo cobro y resultados duplicados.
6. 200 con texto vacío o ilegible
Estos dos casos no tienen error HTTP y la dirección del diagnóstico es completamente distinta.
El texto vacío suele darse con: silencio total o volumen muy bajo; un parámetro de idioma que no coincide con el audio; canal anómalo, con el canal principal sin sonido; una codificación que se puede subir pero falla al decodificar. Haz primero detección de volumen, pasa language=zh explícitamente y prueba una vez convertido a 16 kHz mono.
El texto ilegible o con muchos errores suele deberse a: idioma mal detectado, acento o dialecto marcado, música de fondo mezclada con la voz, varias personas hablando a la vez, micrófono demasiado lejos. Puedes pasar nombres de personas, productos y términos técnicos en prompt y aplicar una tabla de reemplazo después. Si el audio en sí no sirve, cambiar de modelo no lo salvará; vuelve a la grabación y al preprocesamiento.
7. Reintentos y división: un bloque de código reutilizable
Reintentar solo sirve para errores transitorios. Con 401, 400 y 413 hay que cambiar la solicitud; reintentar a ciegas solo amplifica el problema.
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="zh",
response_format="verbose_json",
)
text = (result.text or "").strip()
if not text:
raise ValueError("Transcripción vacía: revisa volumen, idioma y canal")
return text
except RateLimitError:
wait = min(2 ** attempt, 30) + random.random()
print(f"429, reintentando en {wait:.1f}s")
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 requieren cambiar la solicitud, no reintentar
raise RuntimeError("Se agotaron los reintentos")
print(transcribe("reunion.mp3"))
Los nombres de modelo dependen de la documentación del sitio; whisper-1 es solo un ejemplo habitual. Para audios que superan el límite, divide primero con ffmpeg y llama a esta función por cada tramo; al unir, recuerda sumar de nuevo la hora de inicio de cada tramo.
8. Registro de logs y lista para pedir ayuda al proveedor
- Registrar hora, zona horaria, código de estado HTTP y tipo de error.
- Registrar
request-idy si la solicitud fue a la entrada oficial o a la de la puerta de enlace. - Registrar nombre de archivo, codificación real, duración, tamaño, frecuencia de muestreo y número de canales.
- Registrar parámetros clave como
model,languageyresponse_format. - Registrar el número de reintentos, el tiempo de espera de cada uno y el resultado final.
- Registrar si la clave es compartida, la concurrencia del momento y el volumen de la tarea por lotes.
- Preparar un audio mínimo reproducible de 10 a 30 segundos, publicable y sin datos personales.
Al enviarlo al proveedor, no compartas la clave completa ni grabaciones de clientes sin autorización. Una muestra mínima reproducible de forma estable es mucho más útil que describir "a veces da error".
Preguntas frecuentes
413 y 400 son problemas de archivo, ¿cómo se distinguen?
413 suele indicar que el tamaño supera el límite; la solución es comprimir o dividir. 400 se refiere más a formato, parámetros o codificación; la solución es transcodificar y revisar campos. Mira primero el tipo de error y el mensaje, no solo el código de estado.
¿Qué hago si el 429 no se recupera?
Primero distingue si el tipo de error es frecuencia excedida o cuota insuficiente. Para frecuencia: reduce concurrencia, usa cola y separa claves. Para cuota: recarga o cambia de entrada. Si el 429 persiste, no sigas aumentando los reintentos; solo alargas la recuperación.
¿Conviene reintentar directamente tras un tiempo de espera?
Primero determina si la solicitud pudo completarse en el servidor. La transcripción puede haberse facturado; reintentar directamente produce resultados y costos duplicados. Usa un registro de tareas o un diseño idempotente para confirmar el estado antes de reenviar.
¿Una transcripción vacía significa que el modelo está roto?
Casi nunca. Revisa primero volumen, silencios, parámetro de idioma, canales y codificación real. Probar el mismo audio en otra entrada permite distinguir rápidamente si el problema es el audio o el servicio.
¿Cómo distinguir un error de la puerta de enlace de uno oficial?
Conserva request-id y el tipo de error, y lanza la misma solicitud contra las dos entradas. Si la oficial funciona y la puerta de enlace falla, el problema probablemente está en la configuración o el reenvío; si ambas fallan, revisa clave, red y archivo.
Siguiente paso
Primero regístrate en la pasarela de IA de ZSQH y, con un audio de un minuto, practica cada caso: 401, 413, 429 y tiempo de espera; después conecta el monitoreo de producción. La disponibilidad de modelos y los precios figuran en precios de modelos.
Lecturas relacionadas:
