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.