🎁 Novità Registrati gratis, 10 chiamate le offriamo noi. Fino a $1, senza carta.

Speech-to-text

POST /v1/audio/transcriptions

Trascrive l'audio in testo. Compatibile con l'API Audio Transcriptions di OpenAI — lo stesso endpoint serve i modelli OpenAI (Whisper / GPT-4o-transcribe), Google Cloud Chirp, BytePlus Seed ASR e Alibaba Qwen3-ASR, e il gateway instrada verso l'upstream corretto in base all'ID del modello. Accetta un upload multipart/form-data (compatibile con l'SDK OpenAI) oppure un corpo application/json con audio codificato in base64.

Corpo della richiesta

ParametroTipoDescrizione
model*stringID del modello di trascrizione (es. whisper-1, gpt-4o-transcribe, chirp-3, seed-asr-bigmodel, fun-asr, qwen3-asr-flash). Vedi Modelli supportati più sotto.
file*filesolo multipart — il file audio da trascrivere. Obbligatorio a meno che non venga fornito input_audio (JSON).
input_audio*objectsolo JSON — { "data": "<base64>", "format": "mp3" }, oppure { "url": "<fetchable URL>" } per i modelli offline (seed-asr-bigmodel). Da usare al posto di file per le richieste application/json.
response_formatstringFormato di output: json (default; restituisce {text, usage}), text (stringa grezza della trascrizione), verbose_json (segmenti con timestamp), diarized_json (segmenti etichettati per parlante — diarizzazione). I valori consentiti dipendono dal modello; vedi Formati di risposta più sotto.
languagestringSuggerimento ISO-639-1 facoltativo (es. "en") per migliorare accuratezza e latenza.
promptstringTesto facoltativo per guidare lo stile della trascrizione / l'ortografia dei nomi propri.
temperaturenumberTemperatura di campionamento 0–1. Default: 0.
streambooleanSe true, restituisce eventi SSE con trascrizioni parziali. Supportato solo su gpt-4o-transcribe / gpt-4o-mini-transcribe. Gli altri modelli (whisper-1, chirp-2, chirp-3, seed-asr-bigmodel, qwen3-asr-flash) NON supportano lo streaming e restituiscono 400 se stream=true. Default: false.
providerobjectConfigurazione pass-through del provider. Vedi Pass-through del provider più sotto.

Modelli supportati

Non sai quale modello scegliere? Scegli in base a ciò che ti serve

Cosa serveAttivalo conModelli consigliati
Cinese / cantonese, basso costo seed-asr-bigmodel fun-asr
Inglese, alta qualità gpt-4o-transcribe chirp-3
Diarizzazione dei parlanti — chi ha detto cosa response_format=diarized_json seed-asr-bigmodel chirp-3 gpt-4o-transcribe-diarize
Timestamp a livello di parola response_format=verbose_json whisper-1
Sottotitoli in tempo reale (mentre parli) stream=true gpt-4o-transcribe
Registrazioni lunghe / riunioni pass a public URL in input_audio.url seed-asr-bigmodel fun-asr
ModelloProvider · fatturazioneInputDiarizzazioneStreamIdeale per
whisper-1 OpenAI · $0.006/min file Timestamp a livello di parola (verbose_json); la lingua deve essere ISO-639-1
gpt-4o-transcribe OpenAI · token file Inglese, alta precisione; supporta lo streaming
gpt-4o-mini-transcribe OpenAI · token file Multilingue più economico; supporta lo streaming
gpt-4o-transcribe-diarize OpenAI · token file Diarizzazione in inglese; known_speaker_names facoltativo
chirp-3 Google · $0.016/min file Alta qualità; singola chiamata ≤60 s
chirp-2 Google · $0.016/min file USM multilingue; usa chirp-3 per la diarizzazione
seed-asr-bigmodel BytePlus · $0.002/min URL / file Cinese, registrazioni lunghe; il più economico
fun-asr Alibaba · $0.0021/min URL / file Cinese · cantonese · dialetti; registrazioni lunghe
fun-asr-mtl Alibaba · $0.0021/min URL / file Multilingue + diarizzazione
fun-asr-flash Alibaba · $0.0021/min file Multilingue veloce; ≤10 MB, sincrono
qwen3-asr-flash Alibaba · $0.0021/min file Multilingue; ≤5 min/chiamata, fatturazione esatta

Diarization = imposta response_format=diarized_json per ottenere segments[].speaker. Limite di caricamento predefinito 25 MB (vedi Formati audio).

La disponibilità dipende dai canali abilitati per il tuo workspace — chiama /v1/models per vedere cosa puoi usare.

Insidie comuni. (1) Lo streaming (stream=true) funziona solo su gpt-4o-transcribe / gpt-4o-mini-transcribe — tutti gli altri modelli restituiscono 400. (2) input_audio.url (input tramite URL) è supportato solo da seed-asr-bigmodel; tutti gli altri modelli richiedono un file o un upload base64. (3) Il parametro language sui modelli OpenAI (whisper-1, gpt-4o-*) deve essere un codice ISO-639-1 come en o zh — i codici locale come yue-CN vengono rifiutati; Chirp / Seed ASR / Qwen accettano codici locale, oppure ometti language per il rilevamento automatico. (4) Se l'audio supera il limite per richiesta di un modello, suddividilo in blocchi — oppure usa seed-asr-bigmodel (tramite URL) per le registrazioni lunghe (~20 min/richiesta). (5) Audio silenzioso / senza parlato restituisce 200 con una stringa vuota {"text":""}, non un errore.

Formati audio supportati

  • mp3
  • wav
  • ogg
  • flac
  • m4a

Per gli upload multipart il formato viene dedotto dall'estensione del file. Per le richieste base64 (JSON), imposta input_audio.format esplicitamente. Dimensione massima di upload: 25 MB.

Formati di risposta

I valori di response_format accettati dipendono dal modello. json è il default per tutti i modelli (restituisce { text, usage }); text restituisce la stringa grezza della trascrizione.

  • whisper-1json, text, verbose_json
  • gpt-4o-transcribe, gpt-4o-mini-transcribejson, text
  • chirp-3, chirp-2, seed-asr-bigmodel, qwen3-asr-flash, fun-asr-flashjson, text
  • gpt-4o-transcribe-diarize, chirp-3, seed-asr-bigmodel, fun-asr, fun-asr-mtl — also diarized_json (segmenti etichettati per parlante; vedi sotto)

verbose_json (timestamp dei segmenti) è solo per whisper-1. Richiedere un formato non supportato restituisce un 400.

Diarizzazione dei parlanti

Imposta response_format=diarized_json per ottenere segmenti etichettati per parlante — la risposta aggiunge un array segments in cui ogni voce riporta un'etichetta speaker più i timestamp start/end (in secondi). Supportato su gpt-4o-transcribe-diarize (OpenAI), chirp-3 (Google), seed-asr-bigmodel (BytePlus — miglior rapporto qualità-prezzo per il cinese e le registrazioni lunghe) e fun-asr / fun-asr-mtl (Alibaba — file di registrazione offline, accetta un URL o un file). Altri modelli ignorano diarized_json e restituiscono testo semplice; chirp-2 lo rifiuta (usa chirp-3).

Le etichette dei parlanti sono native del provider (ad es. "0"/"1" per chirp-3 e seed-asr, "A"/"B" per gpt-4o-transcribe-diarize); identificano parlanti distinti ma non sono identità reali stabili. Su gpt-4o-transcribe-diarize puoi passare known_speaker_names per orientare l'etichettatura.

# 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

Esempio di risposta

{
  "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": "我这边是客服 有什么可以帮您" }
  ]
}

Esempio di richiesta (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

Esempio di richiesta (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"
}

Esempio — ASR offline (seed-asr-bigmodel)

seed-asr-bigmodel (ASR offline overseas di BytePlus) accetta due input mutuamente esclusivi: un input_audio.url raggiungibile (consigliato — un tuo URL firmato a scadenza verso l'object storage; l'audio non tocca mai il nostro storage), oppure un upload diretto di file/byte (lo depositiamo in un bucket privato e lo eliminiamo subito dopo la trascrizione). Limitazioni: nessuno streaming (stream=true restituisce 400); upload di file fino a 25 MB (usa un URL per registrazioni più grandi); l'elaborazione per singola richiesta è limitata a ~20 minuti, quindi suddividi gli audio molto lunghi. Fatturato in base alla durata dell'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"}}'

Note / avvertenze: (1) language è facoltativo — valori comuni sono zh (mandarino), yue-CN (cantonese), en-US; omettilo per il rilevamento automatico. (2) Quando usi input_audio.url, l'URL deve essere raggiungibile pubblicamente dal servizio di trascrizione — un URL privato/interno/protetto da autenticazione fallirà; un URL firmato a scadenza (pre-signed) verso l'object storage è il modo consigliato. (3) Upload di file e URL sono mutuamente esclusivi; scegline uno. (4) Un audio senza parlato riconoscibile (silenzio) restituisce 200 con una stringa vuota {"text":""}, non un errore.

Esempio — SDK OpenAI Python

L'endpoint è compatibile OpenAI, quindi l'SDK OpenAI ufficiale funziona direttamente sovrascrivendo base_url. Funziona allo stesso modo per whisper-1, gpt-4o-transcribe, chirp-3, seed-asr-bigmodel e qwen3-asr-flash — basta cambiare 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)

Esempio — 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)

Imposta stream=true su gpt-4o-transcribe, gpt-4o-mini-transcribe per ricevere eventi incrementali man mano che l'audio viene decodificato. Il Content-Type della risposta è text/event-stream e gli eventi terminano con data: [DONE]. whisper-1 non supporta lo streaming (restituisce 400 se stream=true).

Tipi di evento che vedrai per 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]

Il gateway emette un oggetto canonico usage documentato sotto Esempio di risposta. L'evento finale usage contiene sempre la suddivisione completa di input_token_details per una fatturazione accurata basata sulla durata audio.

Errori

Tutti gli errori seguono l'envelope OpenAI: { error: { message, type, code, param? } }. Casi comuni:

  • 400 model_not_found — il modello non ha capacità di trascrizione nei canali di questo workspace.
  • 400 byok_strict_no_key — il workspace è in BYOK rigoroso (byok_fallback_to_pool=false) e non ha alcuna chiave nel vault per il provider risolto.
  • 400 content_policy_violation — il campo prompt ha attivato una regola guardrail (es. fuga di una chiave BYOK).
  • 402 quota_exceeded — il costo stimato supera la quota residua del workspace. BYOK è esente.
  • 408 — il corpo della richiesta non ha terminato l'upload entro il timeout di lettura del server. Comune con audio di grandi dimensioni su connessioni lente; riprova o invia un file più piccolo.
  • 413 — l'audio supera il limite di 25 MB.
  • 502 upstream_error — errore di rete upstream o risposta non 2xx dal provider del modello.

Esempio di risposta

{
  "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
    }
  }
}

Oggetto usage uniforme. I modelli di trascrizione fatturati a token (gpt-4o-transcribe / -mini) restituiscono un oggetto usage uniforme — tutti i campi sono sempre presenti, azzerati quando un sotto-conteggio non viene riportato. I modelli OpenAI riportano la suddivisione nativa dell'input audio/testo, quindi per la trascrizione di solo audio input_token_details.audio_tokens == input_tokens vale in genere. cached_tokens è la parte di input servita da una cache lato provider.

whisper-1 è l'unica eccezione: viene fatturato in base alla durata dell'audio, non ai token, quindi la sua risposta non contiene alcun oggetto usage con i token. Con response_format=text il corpo della risposta è la stringa grezza della trascrizione invece di un oggetto JSON.