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

# WebSocket examples

> Stream speech with the SLNG TTS WebSocket API. Python and Node.js code samples for sub-100ms latency, mid-sentence interrupt, and continuous text input.

You need a working knowledge of the [WebSocket protocol](https://slng.mintlify.site/websockets.md). These examples use the Deepgram Aura model; swap the endpoint path to use a different provider.

WebSockets let you stream audio with sub-100ms latency and stop mid-sentence, which is what you need for voice agent conversations. If you only need to generate audio files, [HTTP is simpler](https://slng.mintlify.site/examples/tts-http.md).

## Placeholders

The snippets below use these placeholders. Replace them before running the code.

| Placeholder | Replace with |
| - | - |
| `SLNG_API_KEY` | An SLNG key from [app.slng.ai/api-keys](https://app.slng.ai/api-keys). The snippets read it from the `SLNG_API_KEY` environment variable. |

## Message Flow

Every TTS WebSocket session follows this pattern:

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant SLNG
    Client->>SLNG: Connect wss://api.slng.ai/v1/tts/slng/deepgram/aura:2-en
    SLNG-->>Client: Connection open
    Client->>SLNG: { type: "init", model, voice, config }
    SLNG-->>Client: { type: "ready", session_id: "..." }
    Client->>SLNG: { type: "text", text: "Hello!" }
    SLNG-->>Client: audio chunk
    SLNG-->>Client: audio chunk
    Client->>SLNG: { type: "flush" }
    SLNG-->>Client: audio chunk
    SLNG-->>Client: { type: "flushed" }
    Client->>SLNG: { type: "close" }
```

For the full list of message types and parameters, see the [WebSocket protocol reference](https://slng.mintlify.site/websockets.md). To keep acronyms, names, and domain terms consistent during synthesis, set a session default or per-turn [pronunciation dictionary](https://slng.mintlify.site/pronunciation-dictionaries.md).

***

## Quick Start

Connect, initialize a session, send text, and save the audio to a file.

Both examples write a `output.pcm` file containing raw 16-bit PCM audio at 24 kHz. You can play it with [ffplay](https://ffmpeg.org/ffplay.html):

```bash theme={null}
ffplay -f s16le -ar 24000 -ac 1 output.pcm
```

```javascript JavaScript theme={null}
// npm install ws
const WebSocket = require("ws");
const fs = require("fs");

const API_KEY = process.env.SLNG_API_KEY;
const ws = new WebSocket("wss://api.slng.ai/v1/tts/slng/deepgram/aura:2-en", {
  headers: { Authorization: `Bearer ${API_KEY}` },
});

const audioChunks = [];

ws.on("open", () => {
  // 1. Initialize session
  ws.send(
    JSON.stringify({
      type: "init",
      model: "aura:2-en",
      voice: "aura-2-thalia-en",
      config: {
        encoding: "linear16",
        sample_rate: 24000,
      },
    }),
  );

  // 2. Send text to convert
  ws.send(
    JSON.stringify({
      type: "text",
      text: "Hello! This is a WebSocket TTS example.",
    }),
  );

  // 3. Flush to get remaining audio
  ws.send(JSON.stringify({ type: "flush" }));
});

ws.on("message", (data, isBinary) => {
  if (isBinary) {
    audioChunks.push(data);
  } else {
    const message = JSON.parse(data.toString());
    if (message.type === "ready") {
      console.log("Session ready:", message.session_id);
    } else if (message.type === "flushed") {
      console.log("All audio received, saving to output.pcm");
      fs.writeFileSync("output.pcm", Buffer.concat(audioChunks));
      ws.close();
    } else if (message.type === "error") {
      console.error("Error:", message.message);
      ws.close();
    }
  }
});
```

```python Python theme={null}
# pip install websockets
import asyncio
import json
import os
import websockets

async def tts_quickstart():
    api_key = os.environ["SLNG_API_KEY"]
    uri = "wss://api.slng.ai/v1/tts/slng/deepgram/aura:2-en"
    headers = {"Authorization": f"Bearer {api_key}"}

    async with websockets.connect(uri, extra_headers=headers) as ws:
        # 1. Initialize session
        await ws.send(json.dumps({
            "type": "init",
            "model": "aura:2-en",
            "voice": "aura-2-thalia-en",
            "config": {
                "encoding": "linear16",
                "sample_rate": 24000,
            },
        }))

        # 2. Send text to convert
        await ws.send(json.dumps({
            "type": "text",
            "text": "Hello! This is a WebSocket TTS example.",
        }))

        # 3. Flush to get remaining audio
        await ws.send(json.dumps({"type": "flush"}))

        # 4. Receive audio chunks until flushed
        audio_chunks = []
        async for message in ws:
            if isinstance(message, bytes):
                audio_chunks.append(message)
            else:
                data = json.loads(message)
                if data["type"] == "ready":
                    print(f"Session ready: {data['session_id']}")
                elif data["type"] == "flushed":
                    print("All audio received, saving to output.pcm")
                    break
                elif data["type"] == "error":
                    print(f"Error: {data['message']}")
                    break

        with open("output.pcm", "wb") as f:
            for chunk in audio_chunks:
                f.write(chunk)

asyncio.run(tts_quickstart())
```

***

## More Examples

### Batch Text Streaming

Send multiple sentences for smoother speech instead of one large block. This is a complete example you can run independently.

```javascript JavaScript theme={null}
// npm install ws
const WebSocket = require("ws");
const fs = require("fs");

const API_KEY = process.env.SLNG_API_KEY;
const ws = new WebSocket("wss://api.slng.ai/v1/tts/slng/deepgram/aura:2-en", {
  headers: { Authorization: `Bearer ${API_KEY}` },
});

const text =
  "The sun rose over the mountains. Birds began to sing in the trees. A gentle breeze carried the scent of wildflowers across the valley.";
const audioChunks = [];

ws.on("open", () => {
  ws.send(
    JSON.stringify({
      type: "init",
      model: "aura:2-en",
      voice: "aura-2-thalia-en",
      config: { encoding: "linear16", sample_rate: 24000 },
    }),
  );

  // Stream sentences one at a time
  const sentences = text.split(". ");
  for (const sentence of sentences) {
    ws.send(
      JSON.stringify({
        type: "text",
        text: sentence.endsWith(".") ? sentence : sentence + ".",
      }),
    );
  }

  ws.send(JSON.stringify({ type: "flush" }));
});

ws.on("message", (data, isBinary) => {
  if (isBinary) {
    audioChunks.push(data);
  } else {
    const message = JSON.parse(data.toString());
    if (message.type === "flushed") {
      console.log("All audio received, saving to output.pcm");
      fs.writeFileSync("output.pcm", Buffer.concat(audioChunks));
      ws.close();
    }
  }
});
```

```python Python theme={null}
# pip install websockets
import asyncio
import json
import os
import websockets

async def tts_batch_streaming():
    api_key = os.environ["SLNG_API_KEY"]
    uri = "wss://api.slng.ai/v1/tts/slng/deepgram/aura:2-en"
    headers = {"Authorization": f"Bearer {api_key}"}

    text = (
        "The sun rose over the mountains. "
        "Birds began to sing in the trees. "
        "A gentle breeze carried the scent of wildflowers across the valley."
    )

    async with websockets.connect(uri, extra_headers=headers) as ws:
        await ws.send(json.dumps({
            "type": "init",
            "model": "aura:2-en",
            "voice": "aura-2-thalia-en",
            "config": {"encoding": "linear16", "sample_rate": 24000},
        }))

        # Stream sentences one at a time
        sentences = text.split(". ")
        for sentence in sentences:
            if not sentence.endswith("."):
                sentence += "."
            await ws.send(json.dumps({
                "type": "text",
                "text": sentence,
            }))

        await ws.send(json.dumps({"type": "flush"}))

        # Receive audio chunks until flushed
        audio_chunks = []
        async for message in ws:
            if isinstance(message, bytes):
                audio_chunks.append(message)
            else:
                data = json.loads(message)
                if data["type"] == "flushed":
                    print("All audio received, saving to output.pcm")
                    break

        with open("output.pcm", "wb") as f:
            for chunk in audio_chunks:
                f.write(chunk)

asyncio.run(tts_batch_streaming())
```

***

## Next Steps

> **[Live TTS demo](https://examples-gbcy.onrender.com)**
>
> Try real-time TTS in your browser, no setup needed

> **[WebSocket protocol](https://slng.mintlify.site/websockets.md)**
>
> Full message types, parameters, and error codes

> **[Pronunciation dictionaries](https://slng.mintlify.site/pronunciation-dictionaries.md)**
>
> Reuse pronunciation rules across TTS requests

> **[TTS HTTP examples](https://slng.mintlify.site/examples/tts-http.md)**
>
> Simpler integration for non-streaming use cases

> **[TTS API reference](https://slng.mintlify.site/api-reference/tts/deepgram-aura-2/aura-2-english-ws.md)**
>
> Endpoint-specific parameters


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.