> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cartesia.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket Concurrent Contexts

> Two contexts on one connection, each using ctx.receive() to get their own audio.

<Tabs>
  <Tab title="Python">
    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).

    ```python theme={null}
    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.5",
                voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
                output_format=output_format,
            )
            ctx2 = connection.context(
                model_id="sonic-3.5",
                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}")
    ```

    From [cartesia-python/examples/examples.py:375](https://github.com/cartesia-ai/cartesia-python/blob/main/examples/examples.py#L375)
  </Tab>

  <Tab title="Python (Async)">
    ```python theme={null}
    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.5",
                voice={"mode": "id", "id": "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"},
                output_format=output_format,
            )
            ctx2 = connection.context(
                model_id="sonic-3.5",
                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}")
    ```

    From [cartesia-python/examples/async\_examples.py:288](https://github.com/cartesia-ai/cartesia-python/blob/main/examples/async_examples.py#L288)
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    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.5',
        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.5',
        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}`);
    }
    ```

    From [cartesia-js/examples/node\_examples.ts:239](https://github.com/cartesia-ai/cartesia-js/blob/main/examples/node_examples.ts#L239)
  </Tab>
</Tabs>

## Run this example

<Tabs>
  <Tab title="Python">
    ```sh theme={null}
    cd cartesia-python
    CARTESIA_API_KEY=YOUR_KEY python3 examples/examples.py tts_websocket_concurrent_contexts
    ```
  </Tab>

  <Tab title="Python (Async)">
    ```sh theme={null}
    cd cartesia-python
    CARTESIA_API_KEY=YOUR_KEY python3 examples/async_examples.py tts_websocket_concurrent_contexts_async
    ```
  </Tab>

  <Tab title="TypeScript">
    ```sh theme={null}
    cd cartesia-js
    CARTESIA_API_KEY=YOUR_KEY npx ts-node examples/node_examples.ts ttsWebsocketConcurrentContexts
    ```
  </Tab>
</Tabs>
