Reconnaissance vocale
POST /v1/audio/transcriptions
Transcrit l'audio en texte. Compatible avec l'API OpenAI Audio Transcriptions — le même endpoint sert les modèles OpenAI Whisper / GPT-4o-transcribe et les modèles Google Gemini, et le gateway achemine vers le bon upstream selon l'ID du modèle. Accepte soit un multipart/form-data (compatible avec le SDK OpenAI) ou un corps application/json avec de l'audio encodé en base64.
Corps de la requête
| Paramètre | Type | Description |
|---|---|---|
model* | string | ID du modèle de transcription (par ex. whisper-1, gpt-4o-transcribe, chirp-3, seed-asr-bigmodel, fun-asr, qwen3-asr-flash). Voir « Modèles pris en charge » ci-dessous. |
file* | file | multipart uniquement — le fichier audio à transcrire. Requis sauf si input_audio est fourni (JSON). |
input_audio* | object | JSON uniquement — { "data": "<base64>", "format": "mp3" }, ou { "url": "<fetchable URL>" } pour les modèles hors ligne (seed-asr-bigmodel). À utiliser à la place de file pour les requêtes application/json. |
response_format | string | Format de sortie : json (par défaut ; renvoie {text, usage}), text (chaîne de transcription brute), verbose_json (segments avec horodatages), diarized_json (segments étiquetés par locuteur — diarisation). Les valeurs autorisées dépendent du modèle ; voir « Formats de réponse » ci-dessous. |
language | string | Indice ISO-639-1 facultatif (par ex. "en") pour améliorer la précision et la latence. |
prompt | string | Texte facultatif pour guider le style de transcription / l'orthographe des noms propres. |
temperature | number | Température d'échantillonnage 0–1. Par défaut : 0. |
stream | boolean | Si true, renvoie des événements SSE de transcription partielle (pris en charge sur gpt-4o-transcribe et Gemini). Par défaut : false. |
provider | object | Configuration de pass-through du provider. Voir Pass-through du provider ci-dessous. |
Modèles pris en charge
Vous ne savez pas quel modèle choisir ? Choisissez selon vos besoins
| Ce qu'il vous faut | Activer avec | Modèles recommandés |
|---|---|---|
| Chinois / cantonais, faible coût | — | seed-asr-bigmodel fun-asr |
| Anglais, haute qualité | — | gpt-4o-transcribe chirp-3 |
| Diarisation des locuteurs — qui a dit quoi | response_format=diarized_json | seed-asr-bigmodel chirp-3 gpt-4o-transcribe-diarize |
| Horodatages au niveau du mot | response_format=verbose_json | whisper-1 |
| Sous-titres en temps réel (au fil de la parole) | stream=true | gpt-4o-transcribe |
| Longs enregistrements / réunions | pass a public URL in input_audio.url | seed-asr-bigmodel fun-asr |
| Modèle | Fournisseur · facturation | Entrée | Diarisation | Streaming | Idéal pour |
|---|---|---|---|---|---|
whisper-1 | OpenAI · $0.006/min | file | — | — | Horodatages au niveau du mot (verbose_json) ; la langue doit être en ISO-639-1 |
gpt-4o-transcribe | OpenAI · token | file | — | ✓ | Anglais, haute précision ; prend en charge le streaming |
gpt-4o-mini-transcribe | OpenAI · token | file | — | ✓ | Multilingue moins cher ; prend en charge le streaming |
gpt-4o-transcribe-diarize | OpenAI · token | file | ✓ | — | Diarisation en anglais ; known_speaker_names facultatif |
chirp-3 | Google · $0.016/min | file | ✓ | — | Haute qualité ; un seul appel ≤60 s |
chirp-2 | Google · $0.016/min | file | — | — | USM multilingue ; utilisez chirp-3 pour la diarisation |
seed-asr-bigmodel | BytePlus · $0.002/min | URL / file | ✓ | — | Chinois, longs enregistrements ; le moins cher |
fun-asr | Alibaba · $0.0021/min | URL / file | ✓ | — | Chinois · cantonais · dialectes ; longs enregistrements |
fun-asr-mtl | Alibaba · $0.0021/min | URL / file | ✓ | — | Multilingue + diarisation |
fun-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilingue rapide ; ≤10 MB, synchrone |
qwen3-asr-flash | Alibaba · $0.0021/min | file | — | — | Multilingue ; ≤5 min/appel, facturation exacte |
Diarization = définissez response_format=diarized_json pour obtenir segments[].speaker. Limite d'envoi par défaut 25 MB (voir Formats audio).
Les modèles Google peuvent être servis via l'API Gemini ou, avec une clé de compte de service Vertex BYOK, via Google Cloud Vertex AI. La disponibilité dépend des canaux activés pour votre espace de travail — appelez /v1/models pour voir ce que vous pouvez utiliser.
Pièges courants. (1) Le streaming (stream=true) ne fonctionne que sur gpt-4o-transcribe / gpt-4o-mini-transcribe — tous les autres modèles renvoient 400. (2) input_audio.url (entrée par URL) n'est pris en charge que par seed-asr-bigmodel ; tous les autres modèles requièrent un envoi via file ou base64. (3) Le paramètre language sur les modèles OpenAI (whisper-1, gpt-4o-*) doit être un code ISO-639-1 tel que en ou zh — les codes de locale comme yue-CN sont rejetés ; Chirp / Seed ASR / Qwen acceptent les codes de locale, ou omettez language pour une détection automatique. (4) Si l'audio dépasse la limite par requête d'un modèle, découpez-le en segments — ou utilisez seed-asr-bigmodel (via URL) pour les longs enregistrements (~20 min/requête). (5) Un audio silencieux / sans parole renvoie 200 avec une chaîne vide {"text":""}, et non une erreur.
Formats audio pris en charge
mp3wavoggflacm4a
Pour les téléversements multipart, le format est déduit de l'extension du nom de fichier. Pour les requêtes base64 (JSON), définissez input_audio.format explicitement. Taille maximale de téléversement : 25 Mo.
Formats de réponse
La valeur response_format les valeurs acceptées dépendent du modèle. json est la valeur par défaut pour tous les modèles (renvoie { text, usage }); text renvoie la chaîne brute de transcription.
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(segments étiquetés par locuteur ; voir ci-dessous)
verbose_json (horodatages de segments) est réservé à whisper-1 ;
Diarisation des locuteurs
Définissez response_format=diarized_json pour obtenir des segments étiquetés par locuteur — la réponse ajoute un tableau segments où chaque entrée porte une étiquette speaker ainsi que des horodatages start/end (en secondes). Pris en charge sur gpt-4o-transcribe-diarize (OpenAI), chirp-3 (Google), seed-asr-bigmodel (BytePlus — meilleur rapport qualité-prix pour le chinois et les longs enregistrements), et fun-asr / fun-asr-mtl (Alibaba — fichier d'enregistrement hors ligne, accepte une URL ou un fichier). Les autres modèles ignorent diarized_json et renvoient du texte brut ; chirp-2 le rejette (utilisez chirp-3).
Les étiquettes de locuteur sont propres au fournisseur (p. ex. "0"/"1" pour chirp-3 et seed-asr, "A"/"B" pour gpt-4o-transcribe-diarize) ; elles distinguent des locuteurs mais ne sont pas des identités réelles stables. Sur gpt-4o-transcribe-diarize, vous pouvez passer known_speaker_names pour orienter l'étiquetage.
# 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 Exemple de réponse
{
"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": "我这边是客服 有什么可以帮您" }
]
} Exemple de requête (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 Exemple de requête (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"
} Exemple — ASR hors ligne (seed-asr-bigmodel)
seed-asr-bigmodel (ASR hors ligne BytePlus à l'international) accepte deux entrées mutuellement exclusives : une input_audio.url récupérable (recommandé — votre propre URL signée à durée limitée vers un stockage d'objets ; l'audio ne transite jamais par notre stockage), ou un envoi direct de file/d'octets (nous le stockons temporairement dans un bucket privé et le supprimons juste après la transcription). Limitations : pas de streaming (stream=true renvoie 400) ; les envois de fichiers jusqu'à 25 Mo (utilisez une URL pour des enregistrements plus volumineux) ; le traitement d'une seule requête est plafonné à environ 20 minutes, donc découpez les audios très longs. Facturé selon la durée 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"}}' Notes / pièges : (1) language est facultatif — les valeurs courantes sont zh (mandarin), yue-CN (cantonais), en-US ; omettez-le pour une détection automatique. (2) Lorsque vous utilisez input_audio.url, l'URL doit être publiquement récupérable par le service de transcription — une URL privée/interne/protégée par authentification échouera ; une URL signée (pré-signée) à durée limitée vers un stockage d'objets est la méthode recommandée. (3) L'envoi de fichier et l'URL sont mutuellement exclusifs ; choisissez-en un. (4) Un audio sans parole reconnaissable (silence) renvoie 200 avec une chaîne vide {"text":""}, et non une erreur.
Exemple — SDK OpenAI Python
Le point de terminaison est compatible OpenAI, donc le SDK officiel OpenAI fonctionne directement en remplaçant base_url. Fonctionne de la même manière pour whisper-1, gpt-4o-transcribe et tout modèle de transcription Gemini — il suffit de changer 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) Exemple — 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)
Définissez stream=true sur gpt-4o-transcribe, gpt-4o-mini-transcribe, ou tout modèle de transcription Gemini pour recevoir des événements incrémentaux à mesure que l'audio est décodé. Le Content-Type de la réponse est text/event-stream et les événements se terminent par data: [DONE]. whisper-1 ne prend pas en charge le streaming (renvoie 400 si stream=true).
Types d'événements que vous verrez pour 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] Le streaming Gemini utilise les mêmes noms d'événements SSE, et le gateway émet le même objet canonique usage documenté sous Exemple de réponse— identique entre OpenAI et Gemini — afin que le code client soit portable entre les providers. L'événement final usage transporte toujours le input_token_details détaillé complet pour une facturation précise au tarif audio.
Erreurs
Toutes les erreurs suivent l'enveloppe OpenAI : { error: { message, type, code, param? } }. Cas courants :
400 model_not_found— le modèle ne dispose pas de la capacité de transcription dans les channels de cet espace de travail.400 byok_strict_no_key— l'espace de travail est en BYOK strict (byok_fallback_to_pool=false) et n'a pas de clé vault pour le fournisseur résolu.400 content_policy_violation— le champprompta déclenché une règle de garde-fou (par ex. fuite de clé BYOK).402 quota_exceeded— le coût estimé dépasse le quota restant de l'espace de travail. BYOK est exempté.408— le corps de la requête n'a pas fini de se téléverser dans le délai de lecture du serveur. Fréquent avec un audio volumineux sur une connexion lente ; réessayez ou envoyez un fichier plus petit.413— l'audio dépasse la limite de 25 Mo.502 upstream_error— échec réseau en amont ou réponse non-2xx du fournisseur du modèle.
Exemple de réponse
{
"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
}
}
} Objet usage uniforme. Chaque modèle facturé au token (gpt-4o-*, Gemini, Vertex) renvoie exactement cette structure — tous les champs sont toujours présents, mis à zéro lorsqu'un fournisseur ne signale pas un sous-décompte — de sorte que le même code client lit l'usage chez tous les fournisseurs. Comme l'entrée de transcription est entièrement audio, Gemini/Vertex signalent input_token_details.audio_tokens == input_tokens (pas de répartition texte) ; OpenAI signale sa propre répartition audio/texte native. cached_tokens est la portion de l'entrée servie depuis un cache côté fournisseur.
whisper-1 est la seule exception : il est facturé à la durée audio, et non aux tokens, donc sa réponse ne comporte aucun objet usage de tokens. Avec response_format=text le corps de la réponse est la chaîne brute de transcription au lieu d'un objet JSON.