Fala para texto
POST /v1/audio/transcriptions
Transcreve áudio em texto. Compatível com a API OpenAI Audio Transcriptions — o mesmo endpoint atende aos modelos OpenAI Whisper / GPT-4o-transcribe e aos modelos Google Gemini, e o gateway roteia para o upstream correto pelo ID do modelo. Aceita tanto um multipart/form-data (compatível com o SDK da OpenAI) ou um corpo application/json com áudio codificado em base64.
Corpo da requisição
| Parâmetro | Tipo | Descrição |
|---|---|---|
model* | string | ID do modelo de transcrição (ex.: whisper-1, gpt-4o-transcribe, chirp-3, seed-asr-bigmodel, fun-asr, qwen3-asr-flash). Consulte “Modelos suportados” abaixo. |
file* | file | apenas multipart — o arquivo de áudio a transcrever. Obrigatório, a menos que input_audio seja fornecido (JSON). |
input_audio* | object | Apenas JSON — { "data": "<base64>", "format": "mp3" }, ou { "url": "<fetchable URL>" } para modelos offline (seed-asr-bigmodel). Use no lugar de file para requisições application/json. |
response_format | string | Formato de saída: json (padrão; retorna {text, usage}), text (string de transcrição bruta), verbose_json (segmentos com carimbos de tempo), diarized_json (segmentos rotulados por falante — diarização de falantes). Os valores permitidos dependem do modelo; consulte “Formatos de resposta” abaixo. |
language | string | Dica ISO-639-1 opcional (ex.: "en") para melhorar a precisão e a latência. |
prompt | string | Texto opcional para orientar o estilo de transcrição / a grafia de nomes próprios. |
temperature | number | Temperatura de amostragem 0–1. Padrão: 0. |
stream | boolean | Se true, retorna eventos SSE de transcrição parcial (suportado em gpt-4o-transcribe e Gemini). Padrão: false. |
provider | object | Configuração de pass-through do provider. Veja Pass-through do provider abaixo. |
Modelos suportados
Não sabe qual modelo escolher? Escolha conforme sua necessidade
| Você precisa | Ative com | Modelos recomendados |
|---|---|---|
| Chinês / cantonês, baixo custo | — | seed-asr-bigmodel fun-asr |
| Inglês, alta qualidade | — | gpt-4o-transcribe chirp-3 |
| Diarização de falantes — quem disse o quê | response_format=diarized_json | seed-asr-bigmodel chirp-3 gpt-4o-transcribe-diarize |
| Marcações de tempo por palavra | response_format=verbose_json | whisper-1 |
| Legendas em tempo real (enquanto você fala) | stream=true | gpt-4o-transcribe |
| Gravações longas / reuniões | pass a public URL in input_audio.url | seed-asr-bigmodel fun-asr |
| Modelo | Provedor · cobrança | Entrada | Diarização | Streaming | Ideal para |
|---|---|---|---|---|---|
whisper-1 | OpenAI · $0.006/min | file | — | — | Marcações de tempo por palavra (verbose_json); o idioma deve ser ISO-639-1 |
gpt-4o-transcribe | OpenAI · token | file | — | ✓ | Inglês, alta precisão; suporta streaming |
gpt-4o-mini-transcribe | OpenAI · token | file | — | ✓ | Multilíngue mais barato; suporta streaming |
gpt-4o-transcribe-diarize | OpenAI · token | file | ✓ | — | Diarização em inglês; known_speaker_names opcional |
chirp-3 | Google · $0.016/min | file | ✓ | — | Alta qualidade; chamada única ≤60 s |
chirp-2 | Google · $0.016/min | file | — | — | USM multilíngue; use chirp-3 para diarização |
seed-asr-bigmodel | BytePlus · $0.002/min | URL / file | ✓ | — | Chinês, gravações longas; o mais barato |
fun-asr | Alibaba · $0.0021/min | URL / file | ✓ | — | Chinês · cantonês · dialetos; gravações longas |
fun-asr-mtl | Alibaba · $0.0021/min | URL / file | ✓ | — | Multilíngue + diarização |
fun-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilíngue rápido; ≤10 MB, síncrono |
qwen3-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilíngue; ≤5 min/chamada, cobrança exata |
Diarization = defina response_format=diarized_json para obter segments[].speaker. Limite de upload padrão 25 MB (ver Formatos de áudio).
Os modelos do Google podem ser servidos via API Gemini ou, com uma chave de conta de serviço BYOK do Vertex, via Google Cloud Vertex AI. A disponibilidade depende dos canais habilitados para o seu espaço de trabalho — chame /v1/models para ver o que você pode usar.
Armadilhas comuns. (1) Streaming (stream=true) funciona apenas em gpt-4o-transcribe / gpt-4o-mini-transcribe — todos os outros modelos retornam 400. (2) input_audio.url (entrada por URL) é suportado somente por seed-asr-bigmodel; todos os demais modelos exigem um upload de file ou base64. (3) O parâmetro language nos modelos da OpenAI (whisper-1, gpt-4o-*) deve ser um código ISO-639-1 como en ou zh — códigos de locale como yue-CN são rejeitados; Chirp / Seed ASR / Qwen aceitam códigos de locale, ou omita language para detecção automática. (4) Se o áudio exceder o limite por requisição de um modelo, divida-o em partes — ou use seed-asr-bigmodel (via URL) para gravações longas (~20 min/requisição). (5) Áudio silencioso / sem fala retorna 200 com uma string vazia {"text":""}, e não um erro.
Formatos de áudio suportados
mp3wavoggflacm4a
Para uploads multipart, o formato é inferido da extensão do nome do arquivo. Para solicitações base64 (JSON), defina input_audio.format explicitamente. Tamanho máximo de upload: 25 MB.
Formatos de resposta
O valor response_format os valores aceitos dependem do modelo. json é o padrão para todos os modelos (retorna { text, usage }); text retorna a string bruta da transcrição.
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 rotulados por falante; ver abaixo)
verbose_json (timestamps de segmentos) é exclusivo do whisper-1;
Diarização de locutores
Defina response_format=diarized_json para obter segmentos rotulados por falante — a resposta adiciona um array segments em que cada entrada carrega um rótulo speaker além de marcações de tempo start/end (em segundos). Suportado em gpt-4o-transcribe-diarize (OpenAI), chirp-3 (Google), seed-asr-bigmodel (BytePlus — melhor custo-benefício para chinês e gravações longas) e fun-asr / fun-asr-mtl (Alibaba — arquivo de gravação offline, aceita uma URL ou arquivo). Outros modelos ignoram diarized_json e retornam texto simples; chirp-2 o rejeita (use chirp-3).
Os rótulos de falante são nativos do provedor (por exemplo, "0"/"1" para chirp-3 e seed-asr, "A"/"B" para gpt-4o-transcribe-diarize); eles identificam falantes distintos, mas não são identidades reais estáveis. No gpt-4o-transcribe-diarize você pode passar known_speaker_names para orientar a rotulagem.
# 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 Exemplo de resposta
{
"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": "我这边是客服 有什么可以帮您" }
]
} Solicitação de exemplo (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 Solicitação de exemplo (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"
} Exemplo — ASR offline (seed-asr-bigmodel)
seed-asr-bigmodel (ASR offline internacional da BytePlus) aceita duas entradas mutuamente exclusivas: uma input_audio.url acessível (recomendado — sua própria URL de armazenamento de objetos, assinada e com tempo limitado; o áudio nunca toca nosso armazenamento), ou um upload direto de file/bytes (nós o armazenamos temporariamente em um bucket privado e o excluímos logo após a transcrição). Limitações: sem streaming (stream=true retorna 400); uploads de file de até 25 MB (use uma URL para gravações maiores); o processamento por requisição é limitado a ~20 minutos, então divida áudios muito longos. Cobrado pela duração do áudio ($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 / detalhes importantes: (1) language é opcional — valores comuns são zh (mandarim), yue-CN (cantonês), en-US; omita-o para detecção automática. (2) Ao usar input_audio.url, a URL deve ser publicamente acessível pelo serviço de transcrição — uma URL privada/interna/protegida por autenticação falhará; uma URL de armazenamento de objetos assinada (pre-signed) e com tempo limitado é a forma recomendada. (3) O upload de file e a URL são mutuamente exclusivos; escolha um. (4) Áudio sem fala reconhecível (silêncio) retorna 200 com uma string vazia {"text":""}, e não um erro.
Exemplo — SDK OpenAI Python
O endpoint é compatível com OpenAI, então o SDK oficial da OpenAI funciona diretamente substituindo base_url. Funciona da mesma forma para whisper-1, gpt-4o-transcribe e qualquer modelo de transcrição Gemini — basta alterar 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) Exemplo — SDK OpenAI 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)
Defina stream=true em gpt-4o-transcribe, gpt-4o-mini-transcribe, ou qualquer modelo de transcrição Gemini para receber eventos incrementais à medida que o áudio é decodificado. O Content-Type da resposta é text/event-stream e os eventos terminam com data: [DONE]. whisper-1 não suporta streaming (retorna 400 se stream=true).
Tipos de eventos que você verá 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] O streaming do Gemini usa os mesmos nomes de eventos SSE, e o gateway emite o mesmo objeto canônico usage documentado em Exemplo de resposta— idêntico entre OpenAI e Gemini — para que o código do cliente seja portável entre providers. O evento final usage sempre carrega o input_token_details detalhamento completo para uma cobrança precisa à tarifa de áudio.
Erros
Todos os erros seguem o envelope da OpenAI: { error: { message, type, code, param? } }. Casos comuns:
400 model_not_found— o modelo não tem capacidade de transcrição nos channels deste workspace.400 byok_strict_no_key— o workspace é BYOK estrito (byok_fallback_to_pool=false) e não tem chave de vault para o provedor resolvido.400 content_policy_violation— o campopromptacionou uma regra de guardrail (ex.: vazamento de chave BYOK).402 quota_exceeded— o custo estimado excede a cota restante do espaço de trabalho. BYOK é isento.408— o corpo da requisição não terminou de ser enviado dentro do tempo de leitura do servidor. Comum com áudio grande em conexão lenta; tente novamente ou envie um arquivo menor.413— o áudio excede o limite de 25 MB.502 upstream_error— falha de rede upstream ou resposta não-2xx do provedor do modelo.
Exemplo de resposta
{
"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. Todo modelo cobrado por token (gpt-4o-*, Gemini, Vertex) retorna exatamente este formato — todos os campos sempre presentes, preenchidos com zero quando um provedor não informa uma subcontagem — para que o mesmo código cliente leia o uso em todos os provedores. Como a entrada de transcrição é inteiramente áudio, Gemini/Vertex informam input_token_details.audio_tokens == input_tokens (sem divisão de texto); a OpenAI informa sua divisão nativa de áudio/texto. cached_tokens é a parte da entrada servida a partir de um cache do lado do provedor.
whisper-1 é a única exceção: é cobrado por duração de áudio, não por tokens, então sua resposta não traz objeto usage de tokens. Com response_format=text o corpo da resposta é a string bruta da transcrição em vez de um objeto JSON.