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

# Text-to-Speech WebSocket streaming examples

> Working Python and JavaScript code samples showing how to stream text-to-speech audio over the Telnyx WebSocket TTS endpoint with basic and advanced setups.

## Basic Streaming

<CodeGroup>
  ```python Python theme={null}
  import asyncio
  import json
  import base64
  import websockets

  async def tts_stream():
      url = "wss://api.telnyx.com/v2/text-to-speech/speech?voice=Telnyx.NaturalHD.astra"
      headers = {"Authorization": "Bearer YOUR_API_KEY"}

      async with websockets.connect(url, extra_headers=headers) as ws:
          # 1. Handshake
          await ws.send(json.dumps({"text": " "}))

          # 2. Send text
          await ws.send(json.dumps({"text": "Hello from Telnyx text-to-speech."}))

          # 3. Signal end of input
          await ws.send(json.dumps({"text": ""}))

          # 4. Collect audio
          audio_chunks = []
          async for message in ws:
              data = json.loads(message)

              if data.get("error"):
                  print(f"Error: {data['error']}")
                  break

              if data.get("audio"):
                  audio_chunks.append(base64.b64decode(data["audio"]))

              if data.get("isFinal"):
                  break

      # Save audio
      with open("output.mp3", "wb") as f:
          for chunk in audio_chunks:
              f.write(chunk)

  asyncio.run(tts_stream())
  ```

  ```javascript JavaScript theme={null}
  const WebSocket = require('ws');
  const fs = require('fs');

  const url = 'wss://api.telnyx.com/v2/text-to-speech/speech?voice=Telnyx.NaturalHD.astra';
  const ws = new WebSocket(url, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  });

  const audioChunks = [];

  ws.on('open', () => {
    // 1. Handshake
    ws.send(JSON.stringify({ text: ' ' }));

    // 2. Send text
    ws.send(JSON.stringify({ text: 'Hello from Telnyx text-to-speech.' }));

    // 3. Signal end of input
    ws.send(JSON.stringify({ text: '' }));
  });

  ws.on('message', (raw) => {
    const data = JSON.parse(raw);

    if (data.error) {
      console.error('Error:', data.error);
      ws.close();
      return;
    }

    if (data.audio) {
      audioChunks.push(Buffer.from(data.audio, 'base64'));
    }

    if (data.isFinal) {
      fs.writeFileSync('output.mp3', Buffer.concat(audioChunks));
      ws.close();
    }
  });
  ```
</CodeGroup>

## Conversational (Barge-In)

Send multiple text segments and interrupt mid-synthesis:

```python theme={null}
import asyncio
import json
import base64
import websockets

async def conversational_tts():
    url = "wss://api.telnyx.com/v2/text-to-speech/speech?voice=Telnyx.NaturalHD.astra"
    headers = {"Authorization": "Bearer YOUR_API_KEY"}

    async with websockets.connect(url, extra_headers=headers) as ws:
        # Handshake with voice settings
        await ws.send(json.dumps({
            "text": " ",
            "voice_settings": {"voice_speed": 1.1}
        }))

        # Send first sentence
        await ws.send(json.dumps({"text": "Welcome to the demo."}))

        # Wait for first audio, then interrupt
        async for message in ws:
            data = json.loads(message)
            if data.get("isFinal"):
                break

        # Interrupt and send new text
        await ws.send(json.dumps({"force": true}))
        await ws.send(json.dumps({"text": "Actually, let me start over."}))

        # Collect remaining audio...
        await ws.send(json.dumps({"text": ""}))

        async for message in ws:
            data = json.loads(message)
            if data.get("isFinal"):
                break

asyncio.run(conversational_tts())
```

## LLM Token Streaming

Stream tokens from an LLM directly to TTS. The server buffers text and synthesizes at sentence boundaries:

```python theme={null}
import asyncio
import json
import websockets

async def llm_to_tts(llm_token_stream):
    url = "wss://api.telnyx.com/v2/text-to-speech/speech?voice=Telnyx.NaturalHD.astra"
    headers = {"Authorization": "Bearer YOUR_API_KEY"}

    async with websockets.connect(url, extra_headers=headers) as ws:
        await ws.send(json.dumps({"text": " "}))

        # Stream LLM tokens directly — TTS handles sentence buffering
        for token in llm_token_stream:
            await ws.send(json.dumps({"text": token}))

        # Done — flush remaining
        await ws.send(json.dumps({"text": ""}))
```

<Info>
  Markdown in LLM output is automatically stripped before synthesis — headers, bold, italics, code blocks, and links are converted to plain text.
</Info>
