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

# Dictation Streaming Wire Format

> Learn how to format and send audio chunks for Dictation /ws/transcribe: message format, order, example flow, and audio format and chunking

Use this guide to format and send messages over the **`GET /ws/transcribe`** WebSocket.

Send each message as a UTF-8 **JSON text frame** containing exactly one JSON object. Audio must be **Base64-encoded** and included in the JSON payload. **Do not send audio as a binary WebSocket frame.**

## Message format

Each outbound message is a JSON object with a **`type`** field. For audio chunks, the payload field is **`audioData`**.

### Audio chunks

Send audio with **`type`** set to **`AUDIO`**:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ "type": "AUDIO", "audioData": "<base64-encoded PCM_S16LE audio>" }
```

The **`audioData`** value must be:

* Standard Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648)).
* An encoding of the raw **PCM\_S16LE** bytes you intend to send.
* Sent as a JSON string, regardless of the programming language you use.

<Warning>
  Do not use:

  * Hex encoding.
  * URL-safe Base64.
  * Raw binary inside JSON strings.
</Warning>

### End-of-audio message

When you finish sending audio on the WebSocket, send one **`EVENT`** message with **`event`** set to **`AUDIO_END`**:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ "type": "EVENT", "event": "AUDIO_END" }
```

This message tells the server that no more audio chunks are coming for that stream.

<Warning>
  Do not:

  * End Dictation audio with **`{ "type": "AUDIO", "data": "RU9G" }`**. That is the ambient **`/ws/stream`** pattern.
  * Use custom end markers instead of **`AUDIO_END`** or the inbound **`EOF`** marker. See [Read Dictation transcript frames](/documentation/how-to/audio-streaming/dictation-streaming-transcripts#partial-and-final-transcripts).
  * Use binary signaling in place of the JSON **`AUDIO_END`** message.
</Warning>

<Note>
  Dictation **`/ws/transcribe`** does **not** use **`START_TIME`**, does **not** use ambient-style **`AUDIO`** messages with a **`data`** field, and does **not** use the ambient end marker **`RU9G`**. Use **`audioData`** for chunks, and send an **`EVENT`** message with **`event`** set to **`AUDIO_END`** when you are done sending audio.
</Note>

## Required message order

For each logical stream of audio on the socket:

1. Send one or more **`AUDIO`** messages. Each message includes one **`audioData`** chunk.
2. After the last audio chunk you intend to send on that connection, send one **`EVENT`** message with **`event`** set to **`AUDIO_END`**.

There is **no** **`START_TIME`** step and **no** ambient **`RU9G`** end marker on this endpoint.

## Example flow

This example shows the outbound message sequence for one stream: multiple **`AUDIO`** chunks, followed by **`AUDIO_END`**.

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ "type": "AUDIO", "audioData": "<base64(pcm_s16le chunk 1)>" }
{ "type": "AUDIO", "audioData": "<base64(pcm_s16le chunk 2)>" }

{ "type": "EVENT", "event": "AUDIO_END" }
```

## Audio format and chunking

Use raw **PCM\_S16LE** audio chunks in each **`audioData`** message after Base64 decode.

### Audio streaming recommendations

<CardGroup cols={2}>
  <Card title="Sample Rate of 16 kHz" icon="waveform">
    Stream Dictation audio at **16 kHz**, which matches the capture rate used in the Dictation streaming examples.
  </Card>

  <Card title="Mono Channel" icon="microphone">
    Send a **single mono channel** of audio, not stereo or multi-channel.
  </Card>

  <Card title="PCM_S16LE Encoding" icon="file-audio">
    Encode as **PCM\_S16LE** (PCM signed 16-bit little-endian). Remove WAV headers or decode to raw PCM before you send.
  </Card>

  <Card title="About 100 ms per Chunk" icon="clock">
    For **16 kHz**, mono, **16-bit** audio, about **3200 bytes** per chunk is about **100 ms** of audio. Size chunks to your capture pipeline if your encoder differs.
  </Card>

  <Card title="Stream at Real-Time Speed" icon="gauge">
    Pace audio chunks to match their actual duration and stream at or near real time, rather than sending buffered audio as fast as possible.
  </Card>
</CardGroup>

### PCM vs WAV

**PCM\_S16LE** is raw audio data. **`.wav`** is a container format and usually includes a header before the audio data.

If your source is WAV, skip the **44-byte** header before chunking, or decode the file to raw PCM before sending. Use **`0`** as the offset if your buffer is already raw PCM. Sending WAV headers as PCM reduces recognition quality and makes debugging harder.

### Recommended audio format

* **Encoding**: PCM\_S16LE, PCM signed 16-bit little-endian, same family as **LINEAR16** at **16 kHz** mono in typical capture pipelines.
* **Channels**: Mono.
* **Sample rate**: **16 kHz**, aligned with what your integration expects.

### Chunk size

Send audio in small chunks during streaming. For **16 kHz**, mono, **16-bit** audio, about **3200 bytes** per chunk is a common choice, which is about **100 ms** per message. Size chunks to your capture pipeline if your encoder differs.

### Encode each chunk

For every **`AUDIO`** message:

1. Take raw **PCM\_S16LE** bytes.
2. Encode the bytes using standard Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648)).
3. Send the encoded string as **`audioData`**.

## Related topics

<CardGroup cols={2}>
  <Card title="Stream Dictation Audio" icon="waveform" href="/documentation/how-to/audio-streaming/dictation-streaming" arrow={true}>
    How Dictation streaming works, prerequisites, and when to use `/ws/transcribe`.
  </Card>

  <Card title="Ambient Wire Format" icon="code" href="/documentation/how-to/audio-streaming/websocket-streaming-wire-format-ambient" arrow={true}>
    Outbound message contract for Ambient **`GET /ws/stream`**.
  </Card>

  <Card title="Dictation Transcript Frames" icon="message" href="/documentation/how-to/audio-streaming/dictation-streaming-transcripts" arrow={true}>
    Inbound partial and final transcript frames for `/ws/transcribe`.
  </Card>

  <Card title="Complete the Session" icon="circle-check" href="/documentation/how-to/audio-streaming/websocket-streaming-complete-session" arrow={true}>
    Close the socket, end with REST, and troubleshoot common errors.
  </Card>
</CardGroup>

## Next steps

<Icon icon="file-lines" iconType="solid" /> Follow [Complete the session after streaming](/documentation/how-to/audio-streaming/websocket-streaming-complete-session) to close the socket, end the session, and troubleshoot errors.

<Icon icon="file-lines" iconType="solid" /> Copy the [Dictation WebSocket client code example](/documentation/tutorials/dictation-websocket-code-example) for a full client implementation.

<Icon icon="file-lines" iconType="solid" /> Review [Audio capture and streaming FAQs](/api-reference/faqs/audio-capture-streaming) for codec, chunk size, and reconnect guidance.
