Voz a texto
POST /v1/audio/transcriptions
Transcribe audio a texto. Compatible con la API de OpenAI Audio Transcriptions — el mismo endpoint sirve los modelos OpenAI Whisper / GPT-4o-transcribe y los modelos de Google Gemini, y el gateway enruta al upstream correcto según el ID del modelo. Acepta o bien un multipart/form-data (compatible con el SDK de OpenAI) o un cuerpo application/json con audio codificado en base64.
Cuerpo de la solicitud
| Parámetro | Tipo | Descripción |
|---|---|---|
model* | string | ID del modelo de transcripción (p. ej. whisper-1, gpt-4o-transcribe, chirp-3, seed-asr-bigmodel, fun-asr, qwen3-asr-flash). Consulta «Modelos compatibles» más abajo. |
file* | file | solo multipart — el archivo de audio a transcribir. Obligatorio salvo que se proporcione input_audio (JSON). |
input_audio* | object | Solo JSON — { "data": "<base64>", "format": "mp3" }, o { "url": "<fetchable URL>" } para modelos sin conexión (seed-asr-bigmodel). Úsalo en lugar de file para solicitudes application/json. |
response_format | string | Formato de salida: json (predeterminado; devuelve {text, usage}), text (cadena de transcripción sin formato), verbose_json (segmentos con marcas de tiempo), diarized_json (segmentos etiquetados por hablante — diarización de hablantes). Los valores permitidos dependen del modelo; consulta «Formatos de respuesta» más abajo. |
language | string | Sugerencia ISO-639-1 opcional (p. ej. "en") para mejorar la precisión y la latencia. |
prompt | string | Texto opcional para guiar el estilo de transcripción / la ortografía de nombres propios. |
temperature | number | Temperatura de muestreo 0–1. Por defecto: 0. |
stream | boolean | Si es true, devuelve eventos SSE de transcripción parcial (compatible con gpt-4o-transcribe y Gemini). Por defecto: false. |
provider | object | Configuración de pass-through del provider. Consulta Pass-through del provider más abajo. |
Modelos compatibles
¿No sabes qué modelo elegir? Elige según lo que necesites
| Necesitas | Actívalo con | Modelos recomendados |
|---|---|---|
| Chino / cantonés, bajo costo | — | seed-asr-bigmodel fun-asr |
| Inglés, alta calidad | — | gpt-4o-transcribe chirp-3 |
| Diarización de hablantes: quién dijo qué | response_format=diarized_json | seed-asr-bigmodel chirp-3 gpt-4o-transcribe-diarize |
| Marcas de tiempo por palabra | response_format=verbose_json | whisper-1 |
| Subtítulos en tiempo real (mientras hablas) | stream=true | gpt-4o-transcribe |
| Grabaciones largas / reuniones | pass a public URL in input_audio.url | seed-asr-bigmodel fun-asr |
| Modelo | Proveedor · facturación | Entrada | Diarización | Streaming | Ideal para |
|---|---|---|---|---|---|
whisper-1 | OpenAI · $0.006/min | file | — | — | Marcas de tiempo por palabra (verbose_json); el idioma debe ser ISO-639-1 |
gpt-4o-transcribe | OpenAI · token | file | — | ✓ | Inglés, alta precisión; admite streaming |
gpt-4o-mini-transcribe | OpenAI · token | file | — | ✓ | Multilingüe más económico; admite streaming |
gpt-4o-transcribe-diarize | OpenAI · token | file | ✓ | — | Diarización en inglés; known_speaker_names opcional |
chirp-3 | Google · $0.016/min | file | ✓ | — | Alta calidad; una sola llamada ≤60 s |
chirp-2 | Google · $0.016/min | file | — | — | USM multilingüe; usa chirp-3 para la diarización |
seed-asr-bigmodel | BytePlus · $0.002/min | URL / file | ✓ | — | Chino, grabaciones largas; el más económico |
fun-asr | Alibaba · $0.0021/min | URL / file | ✓ | — | Chino · cantonés · dialectos; grabaciones largas |
fun-asr-mtl | Alibaba · $0.0021/min | URL / file | ✓ | — | Multilingüe + diarización |
fun-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilingüe rápido; ≤10 MB, sincrónico |
qwen3-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilingüe; ≤5 min/llamada, facturación exacta |
Diarization = define response_format=diarized_json para obtener segments[].speaker. Límite de subida predeterminado 25 MB (ver Formatos de audio).
Los modelos de Google pueden servirse a través de la API de Gemini o, con una clave de cuenta de servicio BYOK de Vertex, a través de Google Cloud Vertex AI. La disponibilidad depende de los canales habilitados para tu espacio de trabajo — llama a /v1/models para ver qué puedes usar.
Errores comunes. (1) El streaming (stream=true) funciona solo en gpt-4o-transcribe / gpt-4o-mini-transcribe — cualquier otro modelo devuelve 400. (2) input_audio.url (entrada por URL) solo es compatible con seed-asr-bigmodel; todos los demás modelos requieren una carga de file o base64. (3) El parámetro language en los modelos de OpenAI (whisper-1, gpt-4o-*) debe ser un código ISO-639-1 como en o zh — los códigos de configuración regional como yue-CN se rechazan; Chirp / Seed ASR / Qwen aceptan códigos de configuración regional, o bien omite language para detectar automáticamente. (4) Si el audio supera el límite por solicitud de un modelo, divídelo en fragmentos — o usa seed-asr-bigmodel (mediante URL) para grabaciones largas (~20 min/solicitud). (5) El audio en silencio / sin habla devuelve 200 con una cadena vacía {"text":""}, no un error.
Formatos de audio compatibles
mp3wavoggflacm4a
Para cargas multipart, el formato se infiere de la extensión del nombre de archivo. Para solicitudes base64 (JSON), establece input_audio.format explícitamente. Tamaño máximo de carga: 25 MB.
Formatos de respuesta
El valor response_format los valores aceptados dependen del modelo. json es el valor predeterminado para todos los modelos (devuelve { text, usage }); text devuelve la cadena de transcripción en bruto.
whisper-1—json,text,verbose_jsongpt-4o-transcribe,gpt-4o-mini-transcribe—json,textchirp-3,chirp-2,seed-asr-bigmodel,qwen3-asr-flash,fun-asr-flash—json,textgpt-4o-transcribe-diarize,chirp-3,seed-asr-bigmodel,fun-asr,fun-asr-mtl— alsodiarized_json(segmentos etiquetados por hablante; ver más abajo)
verbose_json (marcas de tiempo de segmentos) es solo para whisper-1;
Diarización de hablantes
Define response_format=diarized_json para obtener segmentos etiquetados por hablante: la respuesta añade un arreglo segments donde cada entrada lleva una etiqueta speaker más marcas de tiempo start/end (en segundos). Compatible con gpt-4o-transcribe-diarize (OpenAI), chirp-3 (Google), seed-asr-bigmodel (BytePlus: la mejor relación calidad-precio para chino y grabaciones largas) y fun-asr / fun-asr-mtl (Alibaba: archivo de grabación sin conexión, acepta una URL o un archivo). Otros modelos ignoran diarized_json y devuelven texto plano; chirp-2 lo rechaza (usa chirp-3).
Las etiquetas de hablante son nativas del proveedor (p. ej., "0"/"1" para chirp-3 y seed-asr, "A"/"B" para gpt-4o-transcribe-diarize); identifican hablantes distintos, pero no son identidades reales estables. En gpt-4o-transcribe-diarize puedes pasar known_speaker_names para orientar el etiquetado.
# Chinese meeting, cheapest diarization (BytePlus seed-asr):
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seed-asr-bigmodel",
"input_audio": { "url": "https://your-bucket/signed/meeting.wav", "language": "zh" },
"response_format": "diarized_json"
}'
# English / highest quality (Google chirp-3, <=60 s per request):
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-F model=chirp-3 \
-F file=@call.wav \
-F response_format=diarized_json Ejemplo de respuesta
{
"task": "transcribe",
"text": "喂 你好 我这边是客服 有什么可以帮您",
"duration": 6.2,
"segments": [
{ "id": 0, "start": 0.10, "end": 0.90, "speaker": "0", "text": "喂 你好" },
{ "id": 1, "start": 1.20, "end": 6.20, "speaker": "1", "text": "我这边是客服 有什么可以帮您" }
]
} Solicitud de ejemplo (multipart)
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-F model=gpt-4o-transcribe \
-F file=@meeting.mp3 \
-F response_format=json \
-F language=en Solicitud de ejemplo (JSON base64)
POST /v1/audio/transcriptions
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"model": "gpt-4o-transcribe",
"input_audio": {
"data": "UklGRiQAAABXQVZFZm10I...",
"format": "wav"
},
"response_format": "json",
"language": "en"
} Ejemplo — ASR sin conexión (seed-asr-bigmodel)
seed-asr-bigmodel (ASR sin conexión internacional de BytePlus) acepta dos entradas mutuamente excluyentes: una input_audio.url accesible (recomendada — tu propia URL firmada de almacenamiento de objetos con tiempo limitado; el audio nunca toca nuestro almacenamiento), o una carga directa de file/bytes (la preparamos en un bucket privado y la eliminamos justo después de la transcripción). Limitaciones: sin streaming (stream=true devuelve 400); las cargas de file admiten hasta 25 MB (usa una URL para grabaciones más grandes); el procesamiento por solicitud está limitado a unos 20 minutos, así que divide los audios muy largos. Facturado por duración del audio ($0.002/min).
# ① Quick test — replace ONLY YOUR_API_KEY and run it (uses our hosted sample audio).
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seed-asr-bigmodel",
"input_audio": {
"url": "https://synthorai-asr-sample-360831509259.s3.us-west-1.amazonaws.com/seed-asr-sample.wav",
"language": "zh"
}
}'
# → {"text":"..."}
# ② Your own audio file (<=25 MB) — replace key + file path.
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-F model=seed-asr-bigmodel \
-F language=zh \
-F file=@/path/to/your-audio.wav
# ③ Your own signed URL (recommended for large files / privacy) — replace key + URL.
curl https://synthorai.io/v1/audio/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"seed-asr-bigmodel","input_audio":{"url":"https://your-bucket/signed/meeting.wav","language":"zh"}}' Notas / detalles: (1) language es opcional — los valores comunes son zh (mandarín), yue-CN (cantonés), en-US; omítelo para detectarlo automáticamente. (2) Al usar input_audio.url, la URL debe ser accesible públicamente por el servicio de transcripción — una URL privada/interna/protegida por autenticación fallará; una URL firmada (pre-firmada) de almacenamiento de objetos con tiempo limitado es la forma recomendada. (3) La carga de file y la URL son mutuamente excluyentes; elige una. (4) El audio sin habla reconocible (silencio) devuelve 200 con una cadena vacía {"text":""}, no un error.
Ejemplo — SDK de OpenAI para Python
El endpoint es compatible con OpenAI, por lo que el SDK oficial de OpenAI funciona directamente al sobrescribir base_url. Funciona igual para whisper-1, gpt-4o-transcribe y cualquier modelo de transcripción Gemini — solo cambia model.
from openai import OpenAI
client = OpenAI(
base_url="https://synthorai.io/v1",
api_key="YOUR_API_KEY",
)
with open("meeting.mp3", "rb") as f:
result = client.audio.transcriptions.create(
model="gpt-4o-transcribe",
file=f,
language="en",
# prompt="Synthorai, BYOK, transcribe", # optional vocabulary hint
response_format="json",
)
print(result.text)
# Token-level usage on gpt-4o-*:
if getattr(result, "usage", None):
print(result.usage) Ejemplo — SDK de OpenAI para Node.js
import OpenAI from "openai";
import fs from "node:fs";
const client = new OpenAI({
baseURL: "https://synthorai.io/v1",
apiKey: process.env.SYNTHORAI_API_KEY,
});
const result = await client.audio.transcriptions.create({
model: "gpt-4o-transcribe",
file: fs.createReadStream("meeting.mp3"),
language: "en",
response_format: "json",
});
console.log(result.text); Streaming (SSE)
Establece stream=true en gpt-4o-transcribe, gpt-4o-mini-transcribe, o cualquier modelo de transcripción Gemini para recibir eventos incrementales a medida que se decodifica el audio. El Content-Type de la respuesta es text/event-stream y los eventos terminan con data: [DONE]. whisper-1 no admite streaming (devuelve 400 si stream=true).
Tipos de eventos que verás para gpt-4o-transcribe:
data: {"type":"transcript.text.delta","delta":"Hello "}
data: {"type":"transcript.text.delta","delta":"world."}
data: {"type":"transcript.text.done","text":"Hello world."}
data: {"type":"usage","usage":{"type":"tokens","input_tokens":689,"output_tokens":287,"total_tokens":976,"input_token_details":{"audio_tokens":689,"text_tokens":0,"cached_tokens":0}}}
data: [DONE] El streaming de Gemini usa los mismos nombres de eventos SSE, y el gateway emite el mismo objeto canónico usage documentado en Ejemplo de respuesta— idéntico entre OpenAI y Gemini — de modo que el código del cliente sea portable entre providers. El evento final usage siempre lleva el input_token_details desglose completo para una facturación precisa a tarifa de audio.
Errores
Todos los errores siguen el envelope de OpenAI: { error: { message, type, code, param? } }. Casos comunes:
400 model_not_found— el modelo no tiene capacidad de transcripción en los channels de este espacio de trabajo.400 byok_strict_no_key— el espacio de trabajo es BYOK estricto (byok_fallback_to_pool=false) y no tiene clave de vault para el proveedor resuelto.400 content_policy_violation— el campopromptactivó una regla de guardrail (p. ej. fuga de clave BYOK).402 quota_exceeded— el costo estimado supera el cupo restante del espacio de trabajo. BYOK está exento.408— el cuerpo de la solicitud no terminó de subirse dentro del tiempo de lectura del servidor. Común con audio grande en una conexión lenta; reintenta o envía un archivo más pequeño.413— el audio supera el límite de 25 MB.502 upstream_error— fallo de red upstream o respuesta no-2xx del proveedor del modelo.
Ejemplo de respuesta
{
"text": "Thanks for joining today's call. Let's get started.",
"usage": {
"type": "tokens",
"input_tokens": 689,
"output_tokens": 287,
"total_tokens": 976,
"input_token_details": {
"audio_tokens": 689,
"text_tokens": 0,
"cached_tokens": 0
}
}
} Objeto usage uniforme. Cada modelo facturado por token (gpt-4o-*, Gemini, Vertex) devuelve exactamente esta estructura — todos los campos siempre presentes, rellenados con cero cuando un proveedor no informa un subconteo — de modo que el mismo código cliente lee el uso en todos los proveedores. Como la entrada de transcripción es totalmente audio, Gemini/Vertex informan input_token_details.audio_tokens == input_tokens (sin separación de texto); OpenAI informa su separación nativa de audio/texto. cached_tokens es la porción de la entrada servida desde una caché del lado del proveedor.
whisper-1 es la única excepción: se factura por duración de audio, no por tokens, por lo que su respuesta no incluye ningún objeto usage de tokens. Con response_format=text el cuerpo de la respuesta es la cadena de transcripción en bruto en lugar de un objeto JSON.