DocumentatieLive transcriptie

Live transcriptie

Stream microfoon- of tabaudio via een WebSocket naar transcript1 en krijg ondertitelregels terug terwijl mensen praten, met optioneel realtime vertaling.

Live transcriptie zet een audiostream om in ondertitelregels terwijl mensen nog praten. Je client stuurt ruwe PCM-audio over een WebSocket, en transcript1 stuurt regels terug die eerst een voorlopige schatting zijn en daarna definitief worden. Voeg translate_to toe en elke regel bevat ook zijn vertaling. Als de sessie eindigt, wordt het resultaat opgeslagen als een gewone transcriptie.

Er zijn geen aparte live-abonnementen: live transcriptie gebruikt hetzelfde minutensaldo als al het andere. Zie Facturatie voor hoe verbonden tijd wordt geteld.

Wanneer gebruik je live

Gebruik live alsGebruik een gewone transcriptie als
De audio nog wordt gemaakt: een gesprek, een lezing, een stream, een video die je nu bekijkt.Je een link of een afgerond bestand hebt.
Je binnen een of twee seconden na het gesproken woord ondertitels nodig hebt.Je de beste nauwkeurigheid wilt en op het resultaat kunt wachten.
Je realtime vertaling naast elke regel wilt.Je een vertaling van een afgerond transcript wilt, of meerdere talen.

Live accepteert alleen audio, als ruwe PCM. Videolinks, uploads, WebM, Opus en MP3 worden niet geaccepteerd. Neem de audio op in je client en zet hem eerst om naar PCM. Audio opnemen in een browser laat zien hoe.

Snel starten met de SDK

Installeer SDK 1.5.0 of nieuwer: npm i @transcript1/sdk@latest. t1.live.start maakt de sessie aan, verbindt en wordt afgerond zodra de sessie is gestart, zodat je meteen audio kunt sturen.

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);

Regels worden ter plekke bijgewerkt. Vervang een regel die je al hebt zodra er een met dezelfde id binnenkomt, of lees ze allemaal uit live.lines. end() rondt de sessie af, wacht op de laatste regels en slaat het transcript op. In de Node.js SDK staan alle methoden en events.

Snel starten met een ruwe WebSocket

Zonder SDK zijn er twee stappen: maak een sessie aan via HTTPS en open daarna de WebSocket met het eenmalige token dat je terugkreeg.

Een sessie aanmaken

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}'

De API antwoordt met 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 is null als save op false staat. Het token is eenmalig en verloopt na 60 seconden, dus verbind meteen. rate is het aantal saldominuten dat per gestarte minuut van deze sessie wordt afgeschreven; zie Facturatie.

De request body accepteert deze velden. Ze zijn allemaal optioneel en de scope is transcriptions:write:

VeldStandaardRegel
languageautoauto, of een taalcode van twee letters die live transcriptie ondersteunt.
translate_togeenEen taalcode van twee letters. Eén doeltaal per sessie. Zie Live vertalen.
diarizefalseLabelt sprekers. Sommige combinaties kunnen geen sprekers labelen, bijvoorbeeld samen met language: "auto", en geven 422. Controleer de mogelijkheden.
audio_formatpcm_s16leDe enige waarde. Het veld bestaat zodat er later formaten bij kunnen komen.
sample_rate16000Een geheel getal van 8000 tot 48000. Alleen mono.
savetruefalse bewaart niets nadat de sessie is afgelopen. Zie Opgeslagen transcripten.

Verbinden en streamen

Open de WebSocket met het token als tweede subprotocol. Dit werkt in browsers en in Node 22+ zonder eigen headers. Wacht op session.started voordat je audio stuurt: binaire frames die eerder worden verstuurd, worden genegeerd en je krijgt een audio_dropped-waarschuwing.

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));

Op Node 20 is er geen ingebouwde WebSocket: gebruik het pakket ws, dat dezelfde vorm new WebSocket(url, protocols) heeft.

De server antwoordt op een geldig token met het subprotocol t1-live en niets anders. Een ongeldig token laat de handshake nooit mislukken: de socket gaat open, je krijgt een error-event en de socket sluit met een 4xxx-code, zodat een browser de echte reden laat zien in plaats van een algemene 1006. Zie Sluitcodes.

Audio opnemen in een browser

Live audio moet 16-bit signed little-endian mono PCM zijn, met de sample_rate van de sessie. Browsers leveren samples als drijvende-kommagetallen, dus converteer ze in een AudioWorklet. Dit fragment neemt de microfoon op als 16 kHz PCM in brokken van 100 ms en verstuurt die via het browser-instappunt van de SDK. getAccessToken geeft een OAuth-toegangstoken terug; zet nooit een API-sleutel in een browser. Zie Beveiliging.

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();
}

De worklet is geschreven voor 16 kHz. Draait de context op een andere samplefrequentie, dan is een brok niet langer 100 ms, maar de PCM blijft correct omdat sampleRate overeenkomt met de context. Om het geluid van een tab of een video op te nemen in plaats van de microfoon, maak je de MediaStream met getDisplayMedia of met captureStream() van een media-element en verbind je hem op dezelfde manier.

Live vertalen

Voeg translate_to toe aan de sessie en transcript1 vertaalt elke regel terwijl hij wordt gesproken.

  • Eén doeltaal per sessie. Voeg achteraf meer talen toe aan het opgeslagen transcript met het vertaal-endpoint.
  • Elke line heeft een origineel (text, final) en een translation-object (language, text, final). translation is null als translate_to niet is ingesteld.
  • Het origineel en de vertaling worden onafhankelijk van elkaar definitief: een regel kan een definitief origineel hebben terwijl de vertaling nog verandert. Toon een regel pas als definitief als beide dat zijn.
  • Een regel die al in de doeltaal is, gebruikt zijn eigen tekst als vertaling en is definitief zodra de regel sluit.
  • Een regel sluit als de spreker pauzeert, de spreker wisselt, een pauze tussen woorden langer is dan 0,9 seconden, de regel twee ondertitelrijen (84 tekens) of 15 seconden bereikt, of je finalize stuurt. Met vertaling aan kan het ongeveer 3 seconden langer duren voordat een regel sluit, omdat de vertaling nog binnenkomt. In dat geval kan de vertaling open blijven (final: false) en blijven groeien nadat het origineel definitief is.
  • Vertalen is gratis. Het kost geen minuten.

Welke doeltalen en taalparen beschikbaar zijn, hangt af van de live spraakprovider. Lees de mogelijkheden in plaats van regels hard te coderen. Een niet-ondersteunde doeltaal geeft 422 unsupported_translation. Een provider kan bijvoorbeeld een expliciete language eisen in plaats van auto, of alleen paren toestaan waar Engels in zit.

WebSocket-protocol

Verbinden

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

Het token reist mee als WebSocket-subprotocol. Het komt nooit in een URL of een toegangslog terecht. Stuur geen Authorization-header: het token is het inlogbewijs. De server pingt elke 30 seconden; browsers en het pakket ws antwoorden automatisch. Een socket die 60 seconden geen pong stuurt, wordt verbroken.

Een geldige verbinding met een sessie die al een socket heeft, vervangt de oude. Zie Hervatten en overnemen.

Berichten van de client

BerichtBetekenis
Binair frameAudio: PCM s16le mono met de sample_rate van de sessie. Elk frame heeft een even lengte en is maximaal 256 KB. Ongeveer 100 ms per frame is een goede grootte.
{"type":"finalize"}Sluit de huidige regel nu, bijvoorbeeld als de video is gepauzeerd.
{"type":"end"}Rond de sessie af en sla hem op. De server antwoordt met session.ended en sluit de socket.
Al het andereEen niet-fatale error met de code invalid_message.

Een frame met een oneven lengte of dat te groot is, is een protocolschending en sluit de socket met 4008.

Begin met audio sturen na session.started. Een client die sneller dan realtime audio stuurt, betaalt voor de audiotijd in plaats van de verbonden tijd (zie Facturatie), dus stuur in het tempo waarin de audio wordt gemaakt.

Server-events

Elk event is een JSON-tekstframe met een type.

EventVerstuurd wanneer
session.startedDe verbinding is geaccepteerd. Stuur vanaf nu audio.
lineEen ondertitelregel is aangemaakt of gewijzigd.
usageNa elke afschrijving.
warningEr is iets dat aandacht nodig heeft, maar de sessie gaat door.
errorEen niet-fataal probleem, of de reden voor een directe sluiting.
reconnectDe server gaat zo herstarten. Hervat de sessie.
session.endedDe sessie is afgelopen en opgeslagen. Het laatste event vóór een normale sluiting.

session.started laat weten of dit een hervatting is en hoeveel audio de sessie al heeft verwerkt:

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

line bevat de volledige huidige staat van één regel, dus vervang de regel die je hebt met dezelfde id. Zie Het line-object.

{
  "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 wordt na elke afschrijving verstuurd, met de verbonden tijd, de audiotijd, het aantal saldominuten dat tot nu toe is afgeschreven en de minuten die je nog hebt:

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

warning heeft een code:

codeBetekenis
balance_lowDe volgende afschrijving zou mislukken. De sessie eindigt met balance_exhausted zodra die aan de beurt is. Wordt niet verstuurd als automatisch opwaarderen aanstaat.
audio_droppedEr kwam audio binnen voordat de sessie klaar was, of er kwam te veel audio binnen terwijl de spraakprovider verbond. De oudste audio is weggegooid.
idle_timeout_soon4 minuten geen audio. De sessie eindigt na 5 minuten zonder audio. Stuur audio om hem aan te houden.
{ "type": "warning", "code": "idle_timeout_soon" }

error heeft een code en een message. Deze codes kunnen op een live socket voorkomen:

codeFataalBetekenis
invalid_messageNeeEen tekstframe dat niet finalize of end is.
invalid_tokenJaHet token is ongeldig, verlopen of al gebruikt. De socket sluit met 4001.
not_foundJaDe sessie bestaat niet. De socket sluit met 4004.
session_endedJaDe sessie is al afgelopen. De socket sluit met 4004.
{ "type": "error", "code": "invalid_message", "message": "Expected {\"type\":\"finalize\"} or {\"type\":\"end\"}" }

reconnect komt voordat de server de socket sluit met 1012, bijvoorbeeld tijdens een deploy. Haal een nieuw token op en hervat.

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

session.ended is het laatste event van elke sessie. De getallen zijn de eindtotalen:

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

Het line-object

VeldBetekenis
idEen 0-gebaseerd nummer dat bij elke regel met één oploopt. Het is de segmentindex in het opgeslagen transcript.
start_ms, end_msBegin en einde in de audiotijd van de sessie. Deze tijd loopt door na heraansluitingen.
speakerHet sprekerlabel als diarize aan staat, anders null. De labels zijn dezelfde als in gewone transcripten.
languageDe gedetecteerde of opgegeven taal van de regel, of null als die nog niet bekend is.
textDe originele tekst tot nu toe.
finaltrue zodra de originele tekst niet meer verandert.
translationnull zonder translate_to, anders language, text en final.

Toon regels met final: false in een lichtere stijl: hun tekst kan nog veranderen. De tekst van een regel met final: true verandert nooit meer en een definitieve regel wordt nooit verwijderd.

De SDK gebruikt camelCase voor regelvelden: startMs, endMs.

Eindredenen

session.ended en GET /v1/live/sessions/:id geven een end_reason:

RedenBetekenis
client_endedJe stuurde end.
balance_exhaustedDe volgende afschrijving mislukte. De sessie eindigt op een minuutgrens en wordt opgeslagen.
idle_timeout5 minuten geen audio.
max_durationDe sessie was 300 minuten verbonden. Start een nieuwe.
disconnectedDe client was langer dan 2 minuten weg zonder te hervatten.
upstream_errorDe spraakprovider faalde.
internal_errorEr ging iets mis aan onze kant.
not_connectedDe sessie kreeg binnen 5 minuten nooit verbinding. Hij wordt nooit in rekening gebracht en is alleen zichtbaar via GET.

Sluitcodes

CodeBetekenis
1000Normale sluiting. Komt altijd na session.ended.
1011Onverwachte serverfout. De server herstelt de sessie: hervat met een nieuw token.
1012Serverherstart. Komt na reconnect: hervat met een nieuw token.
4001Het token is ongeldig, verlopen of al gebruikt.
4004De sessie is niet gevonden of is al afgelopen.
4008Protocolschending: een binair frame met oneven lengte of dat te groot is.
4010Vervangen door een nieuwere verbinding met dezelfde sessie.

Terwijl de API herstart, kan een nieuw WebSocket-verzoek met HTTP 503 worden beantwoord. Probeer het zo opnieuw.

Hervatten en overnemen

Een sessie overleeft een verbroken netwerk, een API-deploy en een crash. Na een verbreking wacht hij 2 minuten op je; daarna eindigt hij als disconnected en wordt hij opgeslagen.

  1. Roep POST /v1/live/sessions/:id/token aan. Het antwoord bevat token, token_expires_at en websocket_url, dezelfde velden als bij het aanmaken van de sessie. Het mislukt met 409 session_ended zodra de sessie is afgelopen.
  2. Open een nieuwe WebSocket met dat token.
  3. session.started komt binnen met resumed: true. offset_ms is de hoeveelheid audio die de sessie al heeft verwerkt: ga vanaf dat punt verder met de audio. De regel-id's lopen door.

Regels die al definitief waren, blijven bewaard. De onafgeronde staart op het moment van de verbreking gaat verloren, dus speel een paar seconden audio vanaf offset_ms opnieuw af als je die buffert. Gaten tijdens het heraansluiten worden niet in rekening gebracht.

Overnemen is dezelfde aanroep. Denkt de server nog dat een socket openstaat, dan vervangt een nieuwe geldige verbinding die, en wordt de oude socket gesloten met 4010 nadat zijn regels zijn opgeslagen. Een hervatting wordt nooit geblokkeerd door de limiet voor gelijktijdige sessies.

De SDK doet dit allemaal voor je: bij een verbreking of een reconnect-event haalt hij een token op en verbindt hij opnieuw met een backoff van 0,5 tot 8 seconden, tot 2 minuten lang, en speelt hij de laatste 10 seconden audio die tijdens het gat zijn verstuurd opnieuw af.

Facturatie

Live transcriptie gebruikt hetzelfde minutensaldo als batchtranscripties.

  • Verbonden tijd wordt in rekening gebracht, vanaf het moment dat de socket wordt geaccepteerd tot hij sluit. Stilte en een gepauzeerde video tellen mee. De tijd tussen een verbreking en een hervatting niet.
  • Per gestarte minuut, minimaal 1. De eerste minuut wordt afgeschreven als de eerste verbinding wordt geaccepteerd, en elke volgende minuut als die begint.
  • Sneller dan realtime wordt als audiotijd gerekend. Als de audio die je stuurt langer is dan de verbonden tijd, wordt de audiotijd gerekend.
  • De rate lees je uit de API. Eén gestarte minuut kost rate saldominuten, naar boven afgerond. De rate is meestal 1 en kan decimalen hebben. Lees de live rate uit rates.live in GET /v1/account, uit rate in GET /v1/live/capabilities en uit rate in de sessie die je aanmaakt. De rate van een sessie staat vast zodra hij is aangemaakt.
  • Vertalen is gratis.
  • Nooit verbonden betekent niet in rekening gebracht. Een sessie die binnen 5 minuten geen verbinding krijgt, eindigt als not_connected.
  • Mislukkingen worden terugbetaald. Als een sessie eindigt met upstream_error of internal_error voordat hij één regel heeft opgeleverd, worden alle afschrijvingen teruggegeven. Een lege sessie door stilte wordt wel in rekening gebracht en leeg opgeslagen.
  • Als het saldo op is en automatisch opwaarderen aanstaat, belast transcript1 je opgeslagen kaart terwijl de sessie blijft streamen, en gaat de sessie door. Staat automatisch opwaarderen uit of gepauzeerd, of mislukt de afschrijving, dan wordt de sessie afgerond, opgeslagen en beëindigd met balance_exhausted op een minuutgrens. De waarschuwing balance_low komt eerst, tenzij automatisch opwaarderen aanstaat.

Een sessie aanmaken geeft 402 insufficient_minutes als je bruikbare saldo lager is dan één gestarte minuut tegen de huidige rate. Staat automatisch opwaarderen aan, dan probeert transcript1 eerst op te waarderen. Zie Facturatie en limieten.

Limieten

FreeMonthlyAnnual
Gelijktijdige live sessies123
  • Een sessie telt mee zolang hij waiting, connected of disconnected is (binnen zijn venster van 2 minuten). Boven de limiet geeft POST /v1/live/sessions 429 too_many_live_sessions met Retry-After: 30.
  • Live sessies tellen niet mee voor je limiet voor actieve jobs.
  • Een sessie duurt maximaal 300 minuten verbonden tijd. Daarna eindigt hij met max_duration.
  • Een sessie zonder audio gedurende 5 minuten eindigt met idle_timeout; na 4 minuten krijg je idle_timeout_soon. Een gepauzeerde stream kost nog steeds verbonden tijd en telt als inactief, dus beëindig de sessie als de pauze lang duurt.
  • transcript1 begrenst ook alle live sessies samen. Zijn ze allemaal in gebruik, dan geeft POST /v1/live/sessions 503 live_capacity, wat je opnieuw mag proberen. Wacht op Retry-After (30 seconden) en probeer het nog eens. Dit wordt alleen gecontroleerd bij het aanmaken van een sessie, nooit midden in een sessie.
  • Sessies aanmaken en tokens ophalen tellen mee voor je requests per minuut.
  • Audio is alleen ruwe PCM: pcm_s16le, mono, 8000 tot 48000 Hz.

Mogelijkheden

GET /v1/live/capabilities beschrijft wat live transcriptie op dit moment ondersteunt, zodat clients nooit regels van de provider hard hoeven te coderen. De scope is 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
}

De lijsten zijn hier ingekort. Lees ze uit de API.

  • translation.pairs is "any" (elke gedetecteerde taal naar elke doeltaal), of een lijst objecten met from en to.
  • translation.requires_language is true als vertalen een expliciete language nodig heeft in plaats van auto.
  • Als live transcriptie niet is geconfigureerd, is het antwoord available: false met alleen rate, en geeft een sessie aanmaken 503 live_unavailable.

Met de SDK: await t1.live.capabilities().

Een sessie opvragen

GET /v1/live/sessions/:id geeft de status van een sessie terug. De scope is 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 is waiting, connected, disconnected of ended. end_reason is null totdat de sessie is afgelopen. Met de SDK: await t1.live.get(id).

Fouten

Requestfouten gebruiken de gebruikelijke foutenvelop. Dit zijn de fouten die POST /v1/live/sessions en de bijbehorende endpoints teruggeven:

HTTP-statuscodeOpnieuw proberenWanneer
422invalid_requestNeeEen veld ontbreekt of is ongeldig, bijvoorbeeld een sample_rate buiten 8000 tot 48000.
422unsupported_languageNeelanguage wordt niet ondersteund voor live transcriptie.
422unsupported_translationNeeDe doeltaal, of het taalpaar, wordt niet ondersteund.
402insufficient_minutesNeeJe bruikbare saldo is lager dan één gestarte minuut tegen de huidige rate.
403email_not_verifiedNeeBevestig eerst je e-mailadres.
429too_many_live_sessionsJaDe gelijktijdige live sessies van je abonnement zijn in gebruik. Wacht op Retry-After.
503live_capacityJaAlle live capaciteit is in gebruik. Wacht op Retry-After (30 seconden).
503live_unavailableNeeLive transcriptie is op dit moment niet beschikbaar.
409session_endedNeePOST /v1/live/sessions/:id/token voor een sessie die is afgelopen.

Problemen op de socket komen binnen als error-events en sluitcodes.

Opgeslagen transcripten

Met save: true (de standaard) wordt de sessie bij het einde opgeslagen als een gewone transcriptie. De audio wordt nooit bewaard.

  • transcription_id krijg je terug als je de sessie aanmaakt. De status is live zolang de sessie loopt en completed erna. Een sessie die nooit verbinding kreeg, laat een transcriptie met status canceled achter.
  • De transcriptie heeft source: { "platform": "live", "session_id": "lv_…" }. Er is geen link of bestand. Het dashboard toont haar als live sessie.
  • Elke regel wordt één segment, met dezelfde index als de id van de regel. Lees het transcript als JSON, tekst, SRT of VTT zoals bij elke andere transcriptie: zie de API-referentie.
  • De live vertaling wordt mee opgeslagen. Lees hem met de parameter translation, zoals beschreven bij Vertalen.
  • Voeg later meer vertaaltalen toe met POST /v1/transcriptions/:id/translations zodra de transcriptie completed is. Zie Vertalen.

Met save: false blijft er niets bewaard nadat de sessie is afgelopen: er is geen transcriptie en transcription_id is null. Je krijgt nog wel elke regel via de socket en de gebruikelijke afschrijving geldt.

Beveiliging

  • Het token dat je krijgt als je een sessie aanmaakt, is eenmalig en verloopt na 60 seconden. Het wordt als WebSocket-subprotocol verstuurd en niet in de URL, zodat het buiten toegangslogs blijft. Een gelekt token is nutteloos zodra het is gebruikt of verlopen.
  • Gebruik een API-sleutel alleen vanaf een server die je zelf beheert. Zet nooit een API-sleutel in een webpagina of een extensie.
  • Laat gebruikers in een browser of extensie inloggen met OAuth en geef het OAuth-toegangstoken door aan getAccessToken van createLiveClient. Het token heeft de scope transcriptions:write nodig om sessies te starten. OAuth-toegangstokens verlopen na 1 uur en bij elke hervatting vraagt de SDK getAccessToken om een nieuw token.
  • Je server kan de sessie ook met zijn API-sleutel aanmaken en alleen de websocket_url en het token aan de browser geven. De client verbindt dan direct. Zonder nieuw token van jou kan hij niet hervatten.

Laatst bijgewerkt 3 november 2026