DocumentazioneTrascrizione live

Trascrizione live

Invia l'audio del microfono o di una scheda a transcript1 via WebSocket e ricevi righe di sottotitoli, con traduzione opzionale in tempo reale, mentre le persone parlano.

La trascrizione live trasforma un flusso audio in righe di sottotitoli mentre le persone stanno ancora parlando. Il tuo client invia audio PCM grezzo su un WebSocket, e transcript1 restituisce righe che partono come una prima ipotesi parziale e poi diventano definitive. Aggiungi translate_to e ogni riga porta con sé anche la traduzione. Alla fine della sessione il risultato viene salvato come una normale trascrizione.

Non esistono piani separati per il live: usa lo stesso saldo di minuti di tutto il resto. In Fatturazione trovi come viene conteggiato il tempo di connessione.

Quando usare il live

Usa il live quandoUsa una trascrizione normale quando
L'audio è ancora in corso: una chiamata, un intervento, una diretta, un video che stai guardando.Hai un link o un file già pronto.
Ti servono i sottotitoli entro un secondo o due dal parlato.Vuoi la massima precisione e puoi aspettare il risultato.
Vuoi la traduzione in tempo reale accanto a ogni riga.Vuoi tradurre una trascrizione già finita, o in più lingue.

Il live accetta solo audio, come PCM grezzo. Non accetta link a video, caricamenti, WebM, Opus o MP3. Acquisisci l'audio nel tuo client e convertilo prima in PCM. Acquisire l'audio in un browser mostra come fare.

Avvio rapido con l'SDK

Installa l'SDK 1.5.0 o successivo: npm i @transcript1/sdk@latest. t1.live.start crea la sessione, si connette e si risolve quando la sessione è partita, quindi puoi inviare l'audio subito.

import { createReadStream } from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';
import { Transcript1 } from '@transcript1/sdk';
 
const t1 = new Transcript1(); // reads TRANSCRIPT1_API_KEY
 
const live = await t1.live.start({ language: 'en', translateTo: 'es', sampleRate: 16000 });
 
live.on('line', line => {
  const mark = line.final ? 'final  ' : 'partial';
  console.log(mark, line.text, '→', line.translation?.text ?? '');
});
live.on('warning', warning => console.warn(warning.code));
 
// speech.pcm: 16 kHz, mono, signed 16-bit little-endian, no header
for await (const chunk of createReadStream('./speech.pcm', { highWaterMark: 3200 })) {
  live.send(chunk);
  await sleep(100); // 3,200 bytes are 100 ms of audio: send at real-time speed
}
 
const result = await live.end();
console.log(result.reason, result.transcriptionId, result.minutesCharged);

Le righe si aggiornano sul posto. Sostituisci una riga che hai già quando ne arriva una con lo stesso id, oppure leggile tutte da live.lines. end() termina la sessione, aspetta le ultime righe e salva la trascrizione. Tutti i metodi e gli eventi sono in SDK per Node.js.

Avvio rapido con un WebSocket diretto

Senza l'SDK i passaggi sono due: creare una sessione via HTTPS e poi aprire il WebSocket con il token monouso che hai ricevuto.

Creare una sessione

curl -X POST https://api.transcript1.com/v1/live/sessions \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"language": "en", "translate_to": "es", "sample_rate": 16000}'

L'API risponde 201:

{
  "id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "status": "waiting",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "websocket_url": "wss://api.transcript1.com/v1/live/sessions/lv_8fK2Lm0PqRsTuVwXyZaBcD/stream",
  "token": "Zk3x...",
  "token_expires_at": "2026-11-02T12:01:00Z",
  "rate": 1
}

transcription_id è null quando save è false. Il token è monouso e scade dopo 60 secondi, quindi connettiti subito. rate è il numero di minuti di saldo addebitati per ogni minuto iniziato di questa sessione; vedi Fatturazione.

Il body della richiesta accetta questi campi. Sono tutti facoltativi, e lo scope richiesto è transcriptions:write:

CampoPredefinitoRegola
languageautoauto, oppure un codice di due lettere supportato dalla trascrizione live.
translate_tonessunoUn codice di due lettere. Una sola lingua di destinazione per sessione. Vedi Tradurre in tempo reale.
diarizefalseEtichetta i parlanti. Alcune configurazioni non lo permettono, per esempio insieme a language: "auto", e rispondono 422. Controlla le funzionalità.
audio_formatpcm_s16leÈ l'unico valore. Il campo esiste per poter aggiungere altri formati in futuro.
sample_rate16000Un intero da 8000 a 48000. Solo mono.
savetrueCon false non viene conservato nulla dopo la fine della sessione. Vedi Trascrizioni salvate.

Connettersi e trasmettere

Apri il WebSocket con il token come secondo sottoprotocollo. Funziona nei browser e in Node 22+ senza header personalizzati. Aspetta session.started prima di inviare audio: i frame binari inviati prima vengono scartati e ricevi un avviso audio_dropped.

import { createReadStream } from 'node:fs';
import { setTimeout as sleep } from 'node:timers/promises';
 
const session = await fetch('https://api.transcript1.com/v1/live/sessions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TRANSCRIPT1_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ language: 'en', translate_to: 'es', sample_rate: 16000 }),
}).then(response => response.json());
 
const ws = new WebSocket(session.websocket_url, ['t1-live', session.token]);
const lines = new Map();
 
ws.addEventListener('message', async message => {
  const event = JSON.parse(message.data);
 
  if (event.type === 'session.started') {
    for await (const chunk of createReadStream('./speech.pcm', { highWaterMark: 3200 })) {
      ws.send(chunk);
      await sleep(100);
    }
    ws.send(JSON.stringify({ type: 'end' }));
  } else if (event.type === 'line') {
    lines.set(event.line.id, event.line); // the full current state: replace by id
    console.log(event.line.final, event.line.text, event.line.translation?.text);
  } else if (event.type === 'session.ended') {
    console.log('ended:', event.reason, event.minutes_charged);
  }
});
 
ws.addEventListener('close', event => console.log('closed', event.code));

Node 20 non ha un WebSocket integrato: usa il pacchetto ws, che ha la stessa forma new WebSocket(url, protocols).

Per un token valido il server risponde con il sottoprotocollo t1-live e nient'altro. Un token errato non fa mai fallire l'handshake: il socket si apre, ricevi un evento error e il socket si chiude con un codice 4xxx, così il browser mostra il motivo reale invece di un generico 1006. Vedi Codici di chiusura.

Acquisire l'audio in un browser

L'audio live deve essere PCM mono a 16 bit con segno, little-endian, alla sample_rate della sessione. I browser forniscono campioni in virgola mobile, quindi convertili in un AudioWorklet. Questo esempio acquisisce il microfono come PCM a 16 kHz in blocchi da 100 ms e lo invia con il punto di accesso browser dell'SDK. getAccessToken restituisce un token di accesso OAuth; non mettere mai una chiave API in un browser. Vedi Sicurezza.

import { createLiveClient } from '@transcript1/sdk/live';
 
const workletSource = `
class Pcm16Processor extends AudioWorkletProcessor {
  constructor() {
    super();
    this.buffer = new Int16Array(1600); // 100 ms at 16 kHz
    this.filled = 0;
  }
 
  process(inputs) {
    const channel = inputs[0][0];
    if (!channel) return true;
    for (let i = 0; i < channel.length; i++) {
      const sample = Math.max(-1, Math.min(1, channel[i]));
      this.buffer[this.filled++] = sample < 0 ? sample * 0x8000 : sample * 0x7fff;
      if (this.filled === this.buffer.length) {
        this.port.postMessage(this.buffer.slice());
        this.filled = 0;
      }
    }
    return true;
  }
}
registerProcessor('pcm16', Pcm16Processor);
`;
 
const client = createLiveClient({ getAccessToken: () => myApp.getOAuthAccessToken() });
 
const stream = await navigator.mediaDevices.getUserMedia({ audio: { channelCount: 1 } });
const context = new AudioContext({ sampleRate: 16000 });
const moduleUrl = URL.createObjectURL(new Blob([workletSource], { type: 'text/javascript' }));
await context.audioWorklet.addModule(moduleUrl);
 
// the context's real rate: a browser that cannot do 16 kHz picks its own
const live = await client.start({ language: 'auto', sampleRate: context.sampleRate });
live.on('line', renderLine);
 
const microphone = context.createMediaStreamSource(stream);
const capture = new AudioWorkletNode(context, 'pcm16');
capture.port.onmessage = event => live.send(event.data); // an Int16Array
const mute = context.createGain();
mute.gain.value = 0;
microphone.connect(capture).connect(mute).connect(context.destination);
 
async function stop() {
  stream.getTracks().forEach(track => track.stop());
  await context.close();
  return live.end();
}

Il worklet è scritto per 16 kHz. Se il contesto gira a un'altra frequenza, i blocchi non durano più 100 ms, ma il PCM resta corretto perché sampleRate coincide con quello del contesto. Per acquisire l'audio di una scheda o di un video invece del microfono, crea il MediaStream con getDisplayMedia o dal captureStream() di un elemento multimediale e collegalo allo stesso modo.

Tradurre in tempo reale

Aggiungi translate_to alla sessione e transcript1 traduce ogni riga mentre viene pronunciata.

  • Una sola lingua di destinazione per sessione. Dopo, aggiungi altre lingue alla trascrizione salvata con l'endpoint delle traduzioni.
  • Ogni line ha un originale (text, final) e un oggetto translation (language, text, final). translation è null quando translate_to non è impostato.
  • L'originale e la traduzione diventano definitivi in modo indipendente: una riga può avere l'originale definitivo mentre la traduzione sta ancora cambiando. Mostra una riga come definitiva quando lo sono entrambi.
  • Una riga che è già nella lingua di destinazione usa il proprio testo come traduzione ed è definitiva quando la riga si chiude.
  • Una riga si chiude quando chi parla fa una pausa, cambia chi parla, una pausa tra le parole supera 0.9 secondi, la riga raggiunge due righe di sottotitoli (84 caratteri) o 15 secondi, oppure invii finalize. Con la traduzione attiva, una riga può impiegare circa 3 secondi in più a chiudersi mentre arriva la traduzione. In quel caso la traduzione può restare aperta (final: false) e continuare a crescere dopo che l'originale è già definitivo.
  • La traduzione è gratuita. Non usa minuti.

Le lingue di destinazione e le coppie di lingue disponibili dipendono dal fornitore del riconoscimento vocale live. Leggi le funzionalità invece di fissare regole nel codice. Una destinazione non supportata restituisce 422 unsupported_translation. Per esempio, un fornitore può richiedere un language esplicito invece di auto, o ammettere solo coppie che includono l'inglese.

Protocollo WebSocket

Connessione

new WebSocket(websocket_url, ['t1-live', token]);

Il token viaggia come sottoprotocollo WebSocket. Non compare mai in un URL né in un log di accesso. Non inviare un header Authorization: il token è la credenziale. Il server invia un ping ogni 30 secondi; i browser e il pacchetto ws rispondono in automatico. Un socket che non invia pong per 60 secondi viene scollegato.

Una connessione valida a una sessione che ha già un socket sostituisce quello vecchio. Vedi Ripresa e subentro.

Messaggi del client

MessaggioSignificato
Frame binarioAudio: PCM s16le mono alla sample_rate della sessione. Ogni frame ha lunghezza pari e al massimo 256 KB. Circa 100 ms per frame è una buona dimensione.
{"type":"finalize"}Chiude subito la riga corrente, per esempio quando il video viene messo in pausa.
{"type":"end"}Termina la sessione e la salva. Il server risponde session.ended e chiude il socket.
Qualsiasi altra cosaUn evento error non fatale con il codice invalid_message.

Un frame di lunghezza dispari o troppo grande è una violazione del protocollo e chiude il socket con 4008.

Inizia a inviare audio dopo session.started. Un client che invia l'audio più velocemente del tempo reale paga il tempo dell'audio invece del tempo di connessione (vedi Fatturazione): invia quindi alla velocità con cui l'audio viene prodotto.

Eventi del server

Ogni evento è un frame di testo JSON con un type.

EventoInviato quando
session.startedLa connessione è stata accettata. Da ora puoi inviare audio.
lineUna riga di sottotitoli è stata creata o modificata.
usageDopo ogni addebito.
warningQualcosa richiede attenzione ma la sessione continua.
errorUn problema non fatale, o il motivo di una chiusura immediata.
reconnectIl server sta per riavviarsi. Riprendi la sessione.
session.endedLa sessione è finita ed è stata salvata. È l'ultimo evento prima di una chiusura normale.

session.started indica se si tratta di una ripresa e quanto audio la sessione ha già elaborato:

{
  "type": "session.started",
  "session_id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "resumed": false,
  "offset_ms": 0
}

line porta lo stato completo e attuale di una riga, quindi sostituisci la riga che hai con lo stesso id. Vedi L'oggetto riga.

{
  "type": "line",
  "line": {
    "id": 12,
    "start_ms": 53120,
    "end_ms": 56040,
    "speaker": null,
    "language": "en",
    "text": "Welcome back to the stream",
    "final": true,
    "translation": { "language": "es", "text": "Bienvenidos de nuevo", "final": false }
  }
}

usage viene inviato dopo ogni addebito, con il tempo di connessione, il tempo dell'audio, i minuti di saldo addebitati finora e i minuti che ti restano:

{
  "type": "usage",
  "connected_ms": 61240,
  "audio_ms": 60100,
  "minutes_charged": 2,
  "minutes_remaining": 898
}

warning ha un code:

codeSignificato
balance_lowIl prossimo addebito fallirebbe. La sessione termina con balance_exhausted quando arriva il momento. Non viene inviato finché la ricarica automatica è attiva.
audio_droppedÈ arrivato audio prima che la sessione fosse pronta, o troppo audio mentre il fornitore vocale si collegava. L'audio più vecchio è stato scartato.
idle_timeout_soonNessun audio da 4 minuti. La sessione termina dopo 5 minuti senza audio. Invia audio per mantenerla.
{ "type": "warning", "code": "idle_timeout_soon" }

error ha un code e un message. Questi codici possono arrivare su un socket live:

codeFataleSignificato
invalid_messageNoUn frame di testo che non è finalize né end.
invalid_tokenSìIl token non è valido, è scaduto o è già stato usato. Il socket si chiude con 4001.
not_foundSìLa sessione non esiste. Il socket si chiude con 4004.
session_endedSìLa sessione è già terminata. Il socket si chiude con 4004.
{ "type": "error", "code": "invalid_message", "message": "Expected {\"type\":\"finalize\"} or {\"type\":\"end\"}" }

reconnect arriva prima che il server chiuda il socket con 1012, per esempio durante un deploy. Ottieni un nuovo token e riprendi.

{ "type": "reconnect", "reason": "server_restart" }

session.ended è l'ultimo evento di ogni sessione. I numeri sono i totali finali:

{
  "type": "session.ended",
  "reason": "client_ended",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "minutes_charged": 3,
  "connected_ms": 142500,
  "audio_ms": 141900
}

L'oggetto riga

CampoSignificato
idUn numero che parte da 0 e aumenta di uno a ogni riga. È l'indice del segmento nella trascrizione salvata.
start_ms, end_msInizio e fine nel tempo audio della sessione. Questo tempo prosegue attraverso le riconnessioni.
speakerL'etichetta del parlante quando diarize è attivo, altrimenti null. Le etichette sono le stesse delle trascrizioni normali.
languageLa lingua rilevata o indicata della riga, oppure null se non è ancora nota.
textIl testo originale finora.
finaltrue quando il testo originale non cambierà più.
translationnull senza translate_to, altrimenti language, text e final.

Mostra le righe con final: false con uno stile più tenue: il loro testo può ancora cambiare. Il testo di una riga con final: true non cambia mai più, e una riga definitiva non viene mai rimossa.

L'SDK usa camelCase per i campi della riga: startMs, endMs.

Motivi di conclusione

session.ended e GET /v1/live/sessions/:id forniscono un end_reason:

MotivoSignificato
client_endedHai inviato end.
balance_exhaustedL'addebito successivo è fallito. La sessione termina al cambio di minuto e viene salvata.
idle_timeoutNessun audio per 5 minuti.
max_durationLa sessione è rimasta connessa per 300 minuti. Avviane una nuova.
disconnectedIl client è stato assente per più di 2 minuti senza riprendere.
upstream_errorIl fornitore del riconoscimento vocale ha avuto un guasto.
internal_errorSi è verificato un errore nei nostri sistemi.
not_connectedLa sessione non si è mai connessa entro 5 minuti. Non viene mai addebitata ed è visibile solo con GET.

Codici di chiusura

CodiceSignificato
1000Chiusura normale. Segue sempre session.ended.
1011Errore imprevisto del server. Il server recupera la sessione: riprendi con un nuovo token.
1012Riavvio del server. Segue reconnect: riprendi con un nuovo token.
4001Il token non è valido, è scaduto o è già stato usato.
4004La sessione non è stata trovata o è già terminata.
4008Violazione del protocollo: un frame binario di lunghezza dispari o troppo grande.
4010Sostituita da una connessione più recente alla stessa sessione.

Durante il riavvio dell'API, una nuova richiesta WebSocket può ricevere HTTP 503. Riprova tra poco.

Ripresa e subentro

Una sessione sopravvive a una caduta di rete, a un deploy dell'API e a un crash. Per 2 minuti dopo una caduta ti aspetta; poi termina come disconnected e viene salvata.

  1. Chiama POST /v1/live/sessions/:id/token. La risposta contiene token, token_expires_at e websocket_url, gli stessi campi di quando hai creato la sessione. Fallisce con 409 session_ended quando la sessione è terminata.
  2. Apri un nuovo WebSocket con quel token.
  3. session.started arriva con resumed: true. offset_ms è la quantità di audio che la sessione ha già elaborato: continua con l'audio da quel punto. Gli id delle righe proseguono.

Le righe già definitive vengono conservate. La parte in corso nel momento della caduta va persa, quindi rinvia qualche secondo di audio da offset_ms se lo tieni in un buffer. Gli intervalli di riconnessione non vengono addebitati.

Il subentro è la stessa chiamata. Se il server crede ancora che un socket sia aperto, una nuova connessione valida lo sostituisce, e il vecchio socket viene chiuso con 4010 dopo il salvataggio delle sue righe. Il limite di sessioni simultanee non blocca mai una ripresa.

L'SDK fa tutto questo per te: in caso di caduta o di evento reconnect ottiene un token e si riconnette con un backoff da 0.5 a 8 secondi per un massimo di 2 minuti, e rinvia gli ultimi 10 secondi di audio inviati durante l'interruzione.

Fatturazione

La trascrizione live attinge allo stesso saldo di minuti delle trascrizioni normali.

  • Si fattura il tempo di connessione, dal momento in cui il socket viene accettato fino alla chiusura. Contano il silenzio e un video in pausa. Il tempo tra una caduta e la ripresa non conta.
  • Per minuto iniziato, con un minimo di 1. Il primo minuto viene addebitato quando la prima connessione è accettata, e ogni minuto successivo quando inizia.
  • Più veloce del tempo reale si fattura come tempo audio. Se l'audio che invii è più lungo del tempo di connessione, si fattura invece il tempo dell'audio.
  • La tariffa si legge dall'API. Un minuto iniziato costa rate minuti di saldo, arrotondati per eccesso. La tariffa di solito è 1 e può avere decimali. Leggi la tariffa live in rates.live di GET /v1/account, in rate di GET /v1/live/capabilities e in rate della sessione che crei. La tariffa di una sessione resta fissa una volta creata.
  • La traduzione è gratuita.
  • Mai connessa, mai addebitata. Una sessione che non si connette entro 5 minuti termina come not_connected.
  • I guasti vengono rimborsati. Se una sessione termina con upstream_error o internal_error prima di produrre una sola riga, ogni addebito viene restituito. Una sessione vuota a causa del silenzio viene addebitata e salvata vuota.
  • Quando il saldo si esaurisce e la ricarica automatica è attiva, transcript1 addebita la carta salvata mentre la sessione continua a trasmettere, e la sessione prosegue. Se la ricarica automatica è disattivata o in pausa, o l'addebito fallisce, la sessione si finalizza, viene salvata e termina con balance_exhausted al cambio di minuto. Prima arriva l'avviso balance_low, a meno che la ricarica automatica sia attiva.

La creazione di una sessione restituisce 402 insufficient_minutes quando il tuo saldo utilizzabile è inferiore a un minuto iniziato alla tariffa attuale. Se la ricarica automatica è attiva, transcript1 prova prima a ricaricare. Vedi Costi e limiti.

Limiti

FreeMonthlyAnnual
Sessioni live simultanee123
  • Una sessione conta finché è waiting, connected o disconnected (entro la sua finestra di 2 minuti). Oltre il limite, POST /v1/live/sessions restituisce 429 too_many_live_sessions con Retry-After: 30.
  • Le sessioni live non contano nel limite delle trascrizioni attive.
  • Una sessione dura al massimo 300 minuti di tempo di connessione. Poi termina con max_duration.
  • Una sessione senza audio per 5 minuti termina con idle_timeout; ricevi idle_timeout_soon dopo 4 minuti. Un flusso in pausa continua a fatturare tempo di connessione e conta come inattivo, quindi termina la sessione se la pausa è lunga.
  • transcript1 limita insieme tutte le sessioni live. Quando sono tutte in uso, POST /v1/live/sessions restituisce 503 live_capacity, che si può riprovare. Aspetta Retry-After (30 secondi) e riprova. Il controllo avviene solo alla creazione di una sessione, mai a metà.
  • Creare sessioni e ottenere token conta nelle tue chiamate al minuto.
  • L'audio è solo PCM grezzo: pcm_s16le, mono, da 8000 a 48000 Hz.

Funzionalità supportate

GET /v1/live/capabilities descrive cosa supporta in questo momento la trascrizione live, così i client non devono mai fissare nel codice le regole del fornitore. Lo scope richiesto è transcriptions:read.

{
  "available": true,
  "auto_language": true,
  "languages": ["en", "es"],
  "translation": {
    "targets": ["es", "de"],
    "pairs": "any",
    "requires_language": false
  },
  "diarize": true,
  "audio_formats": ["pcm_s16le"],
  "sample_rate": { "min": 8000, "max": 48000 },
  "max_session_minutes": 300,
  "rate": 1
}

Qui le liste sono abbreviate. Leggile dall'API.

  • translation.pairs è "any" (qualsiasi lingua rilevata verso qualsiasi destinazione), oppure un elenco di oggetti con from e to.
  • translation.requires_language è true quando la traduzione richiede un language esplicito invece di auto.
  • Quando la trascrizione live non è configurata, la risposta è available: false con solo rate, e la creazione di una sessione restituisce 503 live_unavailable.

Con l'SDK: await t1.live.capabilities().

Leggere una sessione

GET /v1/live/sessions/:id restituisce lo stato di una sessione. Lo scope richiesto è transcriptions:read.

curl https://api.transcript1.com/v1/live/sessions/lv_8fK2Lm0PqRsTuVwXyZaBcD \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
{
  "id": "lv_8fK2Lm0PqRsTuVwXyZaBcD",
  "status": "ended",
  "end_reason": "client_ended",
  "transcription_id": "tr_3NcQvXy7BtHjKd5ErFgLmA",
  "options": {
    "language": "en",
    "translate_to": "es",
    "diarize": false,
    "audio_format": "pcm_s16le",
    "sample_rate": 16000,
    "save": true
  },
  "connected_ms": 142500,
  "audio_ms": 141900,
  "minutes_charged": 3,
  "rate": 1,
  "created_at": "2026-11-02T11:58:12Z",
  "ended_at": "2026-11-02T12:00:35Z"
}

status è waiting, connected, disconnected o ended. end_reason è null finché la sessione non è terminata. Con l'SDK: await t1.live.get(id).

Errori

Gli errori di richiesta usano la solita struttura di errore. Questi sono quelli restituiti da POST /v1/live/sessions e dai suoi endpoint affini:

Stato HTTPcodeSi può riprovare?Quando
422invalid_requestNoUn campo manca o non è valido, per esempio un sample_rate fuori dall'intervallo da 8000 a 48000.
422unsupported_languageNolanguage non è supportato per la trascrizione live.
422unsupported_translationNoLa lingua di destinazione, o la coppia di lingue, non è supportata.
402insufficient_minutesNoIl tuo saldo utilizzabile è inferiore a un minuto iniziato alla tariffa attuale.
403email_not_verifiedNoConferma prima il tuo indirizzo email.
429too_many_live_sessionsSìLe sessioni live simultanee del tuo piano sono tutte in uso. Aspetta Retry-After.
503live_capacitySìTutta la capacità live è in uso. Aspetta Retry-After (30 secondi).
503live_unavailableNoLa trascrizione live non è disponibile al momento.
409session_endedNoPOST /v1/live/sessions/:id/token per una sessione già terminata.

I problemi sul socket arrivano come eventi error e codici di chiusura.

Trascrizioni salvate

Con save: true (il valore predefinito), la sessione viene salvata come una normale trascrizione quando termina. L'audio non viene mai memorizzato.

  • transcription_id viene restituito quando crei la sessione. Il suo stato è live mentre la sessione è in corso e completed dopo la fine. Una sessione che non si è mai connessa lascia una trascrizione canceled.
  • La trascrizione ha source: { "platform": "live", "session_id": "lv_…" }. Non ci sono link né file. La dashboard la elenca come sessione live.
  • Ogni riga diventa un segmento, con lo stesso indice dell'id della riga. Leggi la trascrizione in JSON, testo, SRT o VTT come qualsiasi altra: vedi il riferimento API.
  • La traduzione live viene salvata insieme. Leggila con il parametro translation, come descritto in Traduzione.
  • Più avanti puoi aggiungere altre lingue di traduzione con POST /v1/transcriptions/:id/translations, quando la trascrizione è completed. Vedi Traduzione.

Con save: false non viene conservato nulla dopo la fine della sessione: non c'è nessuna trascrizione e transcription_id è null. Ricevi comunque ogni riga sul socket e vale l'addebito di sempre.

Sicurezza

  • Il token che ricevi quando crei una sessione è monouso e scade dopo 60 secondi. Viene inviato come sottoprotocollo WebSocket, non nell'URL, quindi resta fuori dai log di accesso. Un token trapelato è inutile una volta usato o scaduto.
  • Usa una chiave API solo da un server che controlli. Non mettere mai una chiave API in una pagina web o in un'estensione.
  • In un browser o in un'estensione, fai accedere le persone con OAuth e passa il token di accesso OAuth a getAccessToken di createLiveClient. Il token ha bisogno dello scope transcriptions:write per avviare le sessioni. I token di accesso OAuth scadono dopo 1 ora, e ogni ripresa chiede a getAccessToken un token nuovo.
  • Il tuo server può anche creare la sessione con la sua chiave API e consegnare al browser solo websocket_url e token. Il client si connette allora direttamente, ma non può riprendere la sessione senza un nuovo token da parte tua.

Ultimo aggiornamento 3 novembre 2026