- Python
- Python (Async)
- TypeScript
Since sync code can’t receive from both contexts concurrently, we collect
them sequentially — but the lazy-routing in receive() ensures that events
consumed while reading context 1 are queued for context 2 (and vice-versa).From cartesia-python/examples/examples.py:375
def tts_websocket_concurrent_contexts(client: Cartesia) -> None:
"""Two contexts on one connection, each using ctx.receive() to get their own audio.
Since sync code can't receive from both contexts concurrently, we collect
them sequentially — but the lazy-routing in receive() ensures that events
consumed while reading context 1 are queued for context 2 (and vice-versa).
"""
output_format = {"container": "raw", "encoding": "pcm_f32le", "sample_rate": 44100}
with client.tts.websocket_connect() as connection:
ctx1 = connection.context(
model_id="sonic-3",
voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
output_format=output_format,
)
ctx2 = connection.context(
model_id="sonic-3",
voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
output_format=output_format,
)
# Send to both contexts before receiving
ctx1.push("Context one is speaking now. This is a longer transcript to ensure that audio chunks from both contexts are interleaved on the wire. The quick brown fox jumps over the lazy dog.")
ctx1.no_more_inputs()
ctx2.push("Context two has a different message. We want to verify that the routing logic correctly separates the audio streams. Pack my box with five dozen liquor jugs.")
ctx2.no_more_inputs()
import datetime
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
# Receive from ctx1 — any ctx2 events read from the wire get queued
filename1 = f"tts_concurrent_ctx1_{timestamp}.pcm"
with open(filename1, "wb") as f:
for response in ctx1.receive():
if response.type == "chunk" and response.audio:
f.write(response.audio)
# Receive from ctx2 — picks up queued events first
filename2 = f"tts_concurrent_ctx2_{timestamp}.pcm"
with open(filename2, "wb") as f:
for response in ctx2.receive():
if response.type == "chunk" and response.audio:
f.write(response.audio)
print(f"Saved context 1 audio to {filename1}")
print(f"Saved context 2 audio to {filename2}")
print(f"Play with:")
print(f" ffplay -f f32le -ar 44100 {filename1}")
print(f" ffplay -f f32le -ar 44100 {filename2}")
async def tts_websocket_concurrent_contexts_async(client: AsyncCartesia) -> None:
"""Two contexts on one connection, each using ctx.receive() to get their own audio."""
from cartesia.resources.tts import AsyncWebSocketContext
output_format = {"container": "raw", "encoding": "pcm_f32le", "sample_rate": 44100}
async with client.tts.websocket_connect() as connection:
ctx1 = connection.context(
model_id="sonic-3",
voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
output_format=output_format,
)
ctx2 = connection.context(
model_id="sonic-3",
voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
output_format=output_format,
)
# Send to both contexts
await ctx1.push("Context one is speaking now. This is a longer transcript to ensure that audio chunks from both contexts are interleaved on the wire. The quick brown fox jumps over the lazy dog.")
await ctx1.no_more_inputs()
await ctx2.push("Context two has a different message. We want to verify that the routing logic correctly separates the audio streams. Pack my box with five dozen liquor jugs.")
await ctx2.no_more_inputs()
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
# Receive concurrently via tasks, writing to files
async def collect(ctx: AsyncWebSocketContext, filename: str) -> None:
with open(filename, "wb") as f:
async for response in ctx.receive():
if response.type == "chunk" and response.audio:
f.write(response.audio)
filename1 = f"tts_concurrent_async_ctx1_{timestamp}.pcm"
filename2 = f"tts_concurrent_async_ctx2_{timestamp}.pcm"
await asyncio.gather(
collect(ctx1, filename1),
collect(ctx2, filename2),
)
print(f"Saved context 1 audio to {filename1}")
print(f"Saved context 2 audio to {filename2}")
print(f"Play with:")
print(f" ffplay -f f32le -ar 44100 {filename1}")
print(f" ffplay -f f32le -ar 44100 {filename2}")
async function ttsWebsocketConcurrentContexts(client: Cartesia): Promise<void> {
/** Two contexts on one connection, each using ctx.receive() to get their own audio. */
const ws = await client.tts.websocket();
ws.on('error', (err) => console.error('WS error:', err.message));
const ctx1 = ws.context({
model_id: 'sonic-3',
voice: { mode: 'id', id: '6ccbfb76-1fc6-48f7-b71d-91ac6298247b' },
output_format: { container: 'raw', encoding: 'pcm_f32le', sample_rate: 44100 },
});
const ctx2 = ws.context({
model_id: 'sonic-3',
voice: { mode: 'id', id: '6ccbfb76-1fc6-48f7-b71d-91ac6298247b' },
output_format: { container: 'raw', encoding: 'pcm_f32le', sample_rate: 44100 },
});
// Send to both contexts before receiving.
await ctx1.push({
transcript:
'Context one is speaking now. This is a longer transcript to ensure that ' +
'audio chunks from both contexts are interleaved on the wire. ' +
'The quick brown fox jumps over the lazy dog.',
});
await ctx1.no_more_inputs();
await ctx2.push({
transcript:
'Context two has a different message. We want to verify that the routing ' +
'logic correctly separates the audio streams. ' +
'Pack my box with five dozen liquor jugs.',
});
await ctx2.no_more_inputs();
const ts = timestamp();
async function collect(ctx: { receive: typeof ctx1.receive }, filename: string): Promise<void> {
const file = fs.createWriteStream(filename);
for await (const event of ctx.receive()) {
if (event.type === 'chunk' && event.audio) {
file.write(event.audio);
}
}
file.end();
}
const filename1 = `tts_concurrent_ctx1_${ts}.pcm`;
const filename2 = `tts_concurrent_ctx2_${ts}.pcm`;
await Promise.all([collect(ctx1, filename1), collect(ctx2, filename2)]);
ws.close();
console.log(`Saved context 1 audio to ${filename1}`);
console.log(`Saved context 2 audio to ${filename2}`);
console.log('Play with:');
console.log(` ffplay -f f32le -ar 44100 ${filename1}`);
console.log(` ffplay -f f32le -ar 44100 ${filename2}`);
}
Run this example
- Python
- Python (Async)
- TypeScript
cd cartesia-python
CARTESIA_API_KEY=YOUR_KEY python3 examples/examples.py tts_websocket_concurrent_contexts
cd cartesia-python
CARTESIA_API_KEY=YOUR_KEY python3 examples/async_examples.py tts_websocket_concurrent_contexts_async
cd cartesia-js
CARTESIA_API_KEY=YOUR_KEY npx ts-node examples/node_examples.ts ttsWebsocketConcurrentContexts