Skip to main content
async function ttsWebsocketLowLatency(client: Cartesia): Promise<void> {
  /** Play audio chunks as they arrive for lowest latency. */
  const sampleRate = 44100;
  const audioCtx = new AudioContext({ sampleRate });
  let nextStartTime = audioCtx.currentTime;

  const ws = await client.tts.websocket();

  for await (const event of ws.generate({
    model_id: 'sonic-3',
    transcript: 'Low latency streaming. Each chunk plays as soon as it arrives.',
    voice: { mode: 'id', id: '6ccbfb76-1fc6-48f7-b71d-91ac6298247b' },
    output_format: { container: 'raw', encoding: 'pcm_f32le', sample_rate: sampleRate },
  })) {
    if (event.type === 'chunk' && event.audio) {
      const floats = new Float32Array(
        event.audio.buffer,
        event.audio.byteOffset,
        event.audio.byteLength / 4,
      );

      const audioBuffer = audioCtx.createBuffer(1, floats.length, sampleRate);
      audioBuffer.getChannelData(0).set(floats);

      const source = audioCtx.createBufferSource();
      source.buffer = audioBuffer;
      source.connect(audioCtx.destination);

      // Schedule this chunk right after the previous one
      const startTime = Math.max(nextStartTime, audioCtx.currentTime);
      source.start(startTime);
      nextStartTime = startTime + audioBuffer.duration;
    }
  }

  ws.close();
}
From cartesia-js/examples/browser_examples.ts:127

Run this example

This example runs in the browser. See the Next.js example for a working setup.