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