Desarrolladores

API de transcripción de audio

Transcribe archivos de audio completos con trabajos en cola, estimaciones gratuitas, envíos idempotentes y seguimiento del uso en ambos servidores de API.

En esta página
  1. Puntos de acceso
  2. Preparar un archivo de audio
  3. Enviar un trabajo de transcripción
  4. Clave de idempotencia
  5. Obtener una estimación sin crear un trabajo
  6. Leer la transcripción
  7. Usar api.multitel.net

Esta API transcribe archivos de audio completos mediante trabajos en cola. Envía un archivo, conserva el ID del trabajo devuelto y consulta el trabajo hasta que termine el procesamiento. Envía todas las solicitudes por HTTPS con las credenciales de tu cuenta, ya sean credenciales HTTP Basic como en los ejemplos o un token de API, según se describe en Autenticación. Mantén las credenciales en tu servidor.

Puntos de acceso

Los dos servidores de API, https://api.multi.tel y el servidor de compatibilidad https://api.multitel.net, comparten los mismos trabajos, claves de idempotencia, límites y facturación, todo dentro del ámbito de la cuenta. Se diferencian en la codificación de las cargas y la estructura externa de las respuestas, por lo que debes usar siempre el mismo servidor con un analizador adecuado.

OperaciónMétodo y ruta
Información del servicioGET /v3/speech_to_text
Enviar un trabajoPOST /v3/speech_to_text
Obtener una estimación sin crear un trabajoPOST /v3/speech_to_text/estimate
Consultar un trabajoGET /v3/speech_to_text/JOB_ID
Liquidar un trabajo pendiente de pagoPOST /v3/speech_to_text/JOB_ID/settle
UsoGET /v3/speech_to_text/usage

En api.multi.tel, todas las rutas también están disponibles con el prefijo /v1/speech-to-text en lugar de /v3/speech_to_text, por ejemplo POST /v1/speech-to-text/estimate. En api.multitel.net, usa las rutas /v3/speech_to_text.

La respuesta de información del servicio incluye mode (batch), realtime (false), paidEnabled (si actualmente se aceptan nuevos envíos de pago), pricePerMinuteUsd (0.005), billingUnit (audio_second), maxAudioSeconds (7200) y maxUploadBytes (26214400), junto con una breve description. Consultarla es gratis y funciona aunque los envíos de pago estén deshabilitados; solo devuelve 503 y transcription_unavailable cuando el servicio completo no está disponible.

Preparar un archivo de audio

Usa un archivo de audio completo de un máximo de 25 MiB (26,214,400 bytes) y 2 horas (7,200 segundos). Al enviarlo, el archivo debe reconocerse como un medio MP3, WAV, Ogg, FLAC, MOV o Matroska que contenga una pista de audio, con una duración en sus metadatos mayor que cero y no superior a 7,200 segundos. Un archivo reconocido que no supere estas comprobaciones se rechaza con 422 y unsupported_audio. Actualmente, un archivo que no pueda leerse como ninguno de estos formatos puede rechazarse en cambio con un error del servidor (500); no vuelvas a enviar ese archivo sin modificarlo. La extensión del archivo por sí sola no demuestra su compatibilidad.

Superar estas comprobaciones no garantiza que el audio pueda decodificarse. El audio se procesa como uno o dos canales. Un archivo con más de dos canales de audio, cuyo audio decodificado dure más de 2 horas o que falle al decodificarse durante el procesamiento termina como un trabajo failed, normalmente con decode_failed, y no se cobra. Convierte el audio multicanal a mono o estéreo antes de enviarlo.

La indicación opcional de idioma es un código de dos o tres letras minúsculas para el idioma hablado, como en. Para no indicar un idioma, omite el campo; api.multi.tel rechaza una cadena vacía. Esta indicación orienta el procesamiento, pero no se contrasta con una lista de idiomas compatibles, así que usa un código válido para el idioma hablado.

Enviar un trabajo de transcripción

Envía JSON con Content-Type: application/json a POST https://api.multi.tel/v3/speech_to_text. El cuerpo de la solicitud puede ocupar hasta 35 MiB, suficiente para un archivo del tamaño máximo tras codificarlo en base64; un cuerpo mayor se rechaza con 413.

CampoSignificado
audioBase64Obligatorio. El archivo completo en base64 estándar (A–Z, a–z, 0–9, +, /) con relleno = cuando sea necesario. No añadas un prefijo de URL de datos, saltos de línea ni espacios, y no uses el alfabeto seguro para URL. El valor debe decodificarse a un tamaño de entre 1 byte y 25 MiB y, al volver a codificarse, producir exactamente el mismo texto.
languageIndicación opcional de idioma, como se describe arriba.

Cualquier otra propiedad JSON, incluida idempotency_key, se rechaza con 400 y invalid_transcription_request. Envía la clave en un encabezado.

Clave de idempotencia

Cada envío requiere un encabezado Idempotency-Key de 1 a 190 caracteres. Usa letras ASCII, dígitos, -, _, . y :, sin espacios al principio ni al final: el servidor de compatibilidad elimina los espacios en blanco de los extremos y mide la clave en bytes, por lo que otros caracteres pueden contarse de forma distinta en cada servidor. Una clave ausente o de 191 caracteres o más se rechaza con 400.

Las claves están limitadas a tu cuenta y al servicio de transcripción, y se comparten entre ambos servidores y todas las credenciales de tu cuenta. Volver a enviar la misma clave con el mismo archivo e idioma devuelve el trabajo existente con HTTP 200 y duplicate: true, independientemente de su estado e incluso si el procesamiento se ha actualizado desde su creación, sin otro cargo. Reutilizar una clave con otro archivo o idioma devuelve 409 y idempotency_conflict. Una clave nueva crea un trabajo nuevo incluso para un archivo idéntico, con un cargo separado si el procesamiento termina correctamente.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

node -e 'process.stdout.write(JSON.stringify({audioBase64:require("node:fs").readFileSync("completed-call.mp3").toString("base64"),language:"en"}))' > completed-call.json

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: speech-call-001" \
  --data-binary @completed-call.json \
  -o speech-job.json \
  https://api.multi.tel/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).data.id'

Un trabajo nuevo devuelve HTTP 202 con los campos mostrados abajo, y una repetición devuelve HTTP 200 con el objeto completo del trabajo descrito en Leer la transcripción. Lee el ID del trabajo, un UUID, en data.id. La respuesta de un trabajo nuevo tiene este aspecto (el identificador y los valores son ejemplos):

{
  "status": "success",
  "data": {
    "id": "3f6c1b2e-8a4d-4e7f-9c21-5b0d7e4a9f13",
    "status": "queued",
    "mode": "batch",
    "realtime": false,
    "source": "api",
    "durationSeconds": 90.5,
    "billedSeconds": 91,
    "costUsd": "0.007583334",
    "pricePerMinuteUsd": "0.005"
  }
}

Mientras un trabajo está en cola o procesándose, durationSeconds, billedSeconds y costUsd son estimaciones de los metadatos del archivo. El cargo final utiliza la duración decodificada.

Un envío también puede devolver 402 y insufficient_balance si el saldo de prepago no alcanza para el trabajo junto con tus otros trabajos pendientes; 429 y transcription_queue_full si tu cuenta o el servicio tienen demasiados trabajos pendientes; 429 y audio_validation_busy si la validación de archivos está al máximo de su capacidad; y 503 y paid_transcription_not_enabled mientras la transcripción de pago esté deshabilitada. Reintenta las respuestas 429 y 503 más tarde con la misma clave.

Obtener una estimación sin crear un trabajo

Envía el mismo cuerpo JSON a POST https://api.multi.tel/v3/speech_to_text/estimate. No se necesita una clave de idempotencia. La estimación valida y mide el archivo, pero no lo transcribe, no crea un trabajo, no reserva fondos, no comprueba tu saldo ni cobra a tu cuenta. Se acepta una indicación language, pero no afecta a la estimación.

Una estimación correcta devuelve HTTP 200 con estimate: true, charged: false, mode, realtime, durationSeconds, billedSeconds, pricePerMinuteUsd y costUsd dentro de data. Usa la duración de los metadatos del archivo, mientras que un trabajo completado se cobra según su duración decodificada, que puede ser distinta. Las estimaciones aplican las mismas comprobaciones de archivos que los envíos. Solo están disponibles mientras la transcripción de pago esté habilitada (de lo contrario, 503 y paid_transcription_not_enabled). Pueden devolver 429 y audio_validation_busy si la validación de archivos está al máximo de su capacidad; reintenta tras una breve espera.

Leer la transcripción

Consulta periódicamente GET /v3/speech_to_text/JOB_ID como se describe en la guía del flujo de trabajo. El objeto del trabajo contiene estos campos:

CampoSignificado
idEl UUID del trabajo.
statusqueued, running, completed, failed o awaiting_payment.
progressUn porcentaje de 0 a 99 durante el procesamiento, si está disponible; 100 al completarse; de lo contrario, null.
durationSeconds, billedSecondsDuración del audio y segundos enteros facturados. Son estimaciones de metadatos mientras el trabajo está en cola o procesándose; una vez completado o pendiente de pago, usan la duración decodificada.
costUsd, costIsEstimateEl coste en dólares estadounidenses, como cadena decimal con nueve cifras decimales. costIsEstimate es true mientras el trabajo está en cola o procesándose. Un trabajo fallido no se cobra, aunque su costUsd siga mostrando la estimación.
pricePerMinuteUsd0.005 para trabajos de la API y 0.000 para trabajos gratuitos de grabaciones de Hosted PBX.
failureCodePara un trabajo fallido: decode_failed (no se pudo decodificar el audio, por ejemplo, porque tiene más de dos canales o dura más de 2 horas una vez decodificado), inference_timeout (el procesamiento tardó demasiado), service_error o worker_lease_lost (se interrumpió el procesamiento). También están definidos los códigos unsupported_audio y quality_check_failed. Un trabajo pendiente de pago muestra insufficient_balance, que puede permanecer después de liquidar el trabajo.
source, modelVersion, createdAtsource es api para envíos de la API, o hpbx para un trabajo de grabación de Hosted PBX de tu cuenta. modelVersion es una cadena opaca que identifica la versión de procesamiento. createdAt es la fecha y hora del envío.
duplicatetrue en las respuestas que devuelven un trabajo existente.
resultSolo está presente cuando status es completed.
Campo del resultadoSignificado
textLa transcripción completa: los textos de todos los segmentos unidos con saltos de línea, en el orden de los segmentos.
segmentsUn array de segmentos ordenados por su inicio. Cada segmento cubre una sección de audio de hasta unos 29 segundos. Sus campos start y end (segundos desde el inicio del audio) delimitan esa sección, no palabras ni frases individuales, y las secciones consecutivas pueden solaparse hasta 1 segundo. Cada segmento también tiene text y language (un código de idioma, que puede estar vacío), además de channel en los resultados de dos canales.
channelCount1 o 2. Está presente en los resultados actuales; los antiguos pueden omitirlo.
audioDurationMsLa duración decodificada en milisegundos. La facturación la redondea hacia arriba a segundos enteros.
qualityFlagsVacío, o review_recommended junto con repetition_detected (una frase se repite con una frecuencia inusual dentro de una sección), no_speech (no se transcribió habla), o ambos.
pipelineVersionPuede aparecer. Un identificador opaco del procesamiento.

Las transcripciones y sus marcas de tiempo, etiquetas de idioma y de canal se generan automáticamente y no se garantiza su exactitud. Cualquier indicador de calidad es un motivo para revisar el resultado; compara los nombres, números y compromisos importantes con el audio original. Los silencios largos y los pasajes muy tenues se omiten y no generan segmentos. Los resultados no identifican a cada hablante. Cuando un resultado indica un channelCount de 2, cada segmento tiene un channel con valor A (el primer canal o canal izquierdo) o B (el segundo canal o canal derecho). Esto solo separa a los hablantes si cada uno se grabó en un canal distinto. El audio de dos canales se factura una sola vez según su duración transcurrida, no por canal. Los resultados mono no tienen etiquetas de canal.

Usar api.multitel.net

El punto de acceso de compatibilidad POST https://api.multitel.net/v3/speech_to_text acepta multipart/form-data con una parte de archivo audio y un campo opcional language, en lugar del campo JSON audioBase64. Un valor vacío de language se trata como ausencia de indicación. Envía el mismo encabezado Idempotency-Key. Si falta el encabezado, este servidor también acepta un campo de formulario idempotency_key. Los campos llamados source, free, billing_source, realtime o stream se rechazan con 400 y unsupported_transcription_option; los demás campos del formulario se ignoran. Este servidor también devuelve estos errores:

  • 400 idempotency_key_required si la clave falta o es demasiado larga.
  • 400 audio_upload_required si falta la carga o no se recibió completa.
  • 400 invalid_language si el idioma no es válido.
  • 413 invalid_audio_size si el archivo está vacío o supera el tamaño máximo.
  • 400 invalid_job si el ID del trabajo tiene un formato incorrecto.

Las respuestas del servicio de transcripción de este servidor usan la estructura externa {"status":{"code":HTTP_STATUS},"response":{...}}. Ten en cuenta que status es un objeto, no una cadena. En caso de éxito, response contiene el mismo objeto que data en el servidor principal, por lo que el ID del trabajo es response.id. En caso de error, response.code contiene el código de error; no se incluye ningún mensaje ni ID de solicitud. Los fallos de autenticación (401) los devuelve la comprobación general de inicio de sesión del servidor y pueden tener un cuerpo distinto, por lo que debes revisar el estado HTTP antes de analizar la respuesta. No intercambies la codificación de carga ni el analizador de respuestas entre servidores.

Para obtener una estimación en este servidor, envía mediante POST los mismos campos multipart a /v3/speech_to_text/estimate. No se necesita clave de idempotencia y la estimación está dentro de response.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Idempotency-Key: speech-call-001" \
  -F "audio=@completed-call.mp3" -F "language=en" \
  -o speech-job.json \
  https://api.multitel.net/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).response.id'