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

# Stream Message Audio

> Stream synthesized speech audio for a chat message

Convert a chat message to speech and stream the audio. Audio is generated via our TTS provider on first request and cached automatically — subsequent requests are served from cache with no added latency.

<Note>
  The response is a **WAV stream** (RIFF container, IEEE float32 PCM, mono, 44.1 kHz). Standard audio players — browser `<audio>`, Web Audio `decodeAudioData`, `ffplay`, `afplay`, `expo-av` — play it directly with no custom decoding.
</Note>

## Request

<ParamField header="Authorization" type="string" required>
  Bearer token obtained from the authenticate endpoint.
</ParamField>

<ParamField path="message_id" type="string" required>
  ID of the chat message to synthesize. The message must belong to your organization.
</ParamField>

## Response

Returns a streaming `audio/wav` body.

| Property            | Value                                         |
| ------------------- | --------------------------------------------- |
| Content-Type        | `audio/wav`                                   |
| Container           | WAV (RIFF)                                    |
| Encoding            | PCM float32, little-endian                    |
| Sample rate         | 44100 Hz                                      |
| Channels            | Mono                                          |
| Content-Disposition | `inline; filename="message-{message_id}.wav"` |

During the first request for a message the audio is streamed live; the WAV header's size fields are written as `0xFFFFFFFF` (read-until-EOF). Cached responses carry real sizes, so seek and duration work from the first byte.

## Playback

### Browser (Web Audio API)

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
async function playMessageAudio(messageId, token) {
  const response = await fetch(
    `https://api.trellis.sh/v1/tts/messages/${messageId}/audio`,
    { headers: { Authorization: `Bearer ${token}` } }
  );

  const audioCtx = new AudioContext();
  const audioBuffer = await audioCtx.decodeAudioData(await response.arrayBuffer());

  const source = audioCtx.createBufferSource();
  source.buffer = audioBuffer;
  source.connect(audioCtx.destination);
  source.start();
}
```

### Browser (`<audio>` element)

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
async function playMessageAudio(messageId, token) {
  const response = await fetch(
    `https://api.trellis.sh/v1/tts/messages/${messageId}/audio`,
    { headers: { Authorization: `Bearer ${token}` } }
  );
  const blob = await response.blob();
  const audio = new Audio(URL.createObjectURL(blob));
  await audio.play();
}
```

### React Native (Expo AV)

```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { Audio } from "expo-av";
import * as FileSystem from "expo-file-system";

async function playMessageAudio(messageId, token) {
  const localPath = FileSystem.cacheDirectory + `${messageId}.wav`;

  await FileSystem.downloadAsync(
    `https://api.trellis.sh/v1/tts/messages/${messageId}/audio`,
    localPath,
    { headers: { Authorization: `Bearer ${token}` } }
  );

  const { sound } = await Audio.Sound.createAsync({ uri: localPath });
  await sound.playAsync();
}
```

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X GET "https://api.trellis.sh/v1/tts/messages/8f14e45f-ceea-467f-a83c-0a06b8901a45/audio" \
    -H "Authorization: Bearer YOUR_TOKEN" \
    --output message_audio.wav
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  message_id = "8f14e45f-ceea-467f-a83c-0a06b8901a45"

  response = requests.get(
      f"https://api.trellis.sh/v1/tts/messages/{message_id}/audio",
      headers={"Authorization": "Bearer YOUR_TOKEN"},
      stream=True,
  )

  with open("message_audio.wav", "wb") as f:
      for chunk in response.iter_content(chunk_size=4096):
          f.write(chunk)
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const messageId = "8f14e45f-ceea-467f-a83c-0a06b8901a45";

  const response = await fetch(
    `https://api.trellis.sh/v1/tts/messages/${messageId}/audio`,
    {
      headers: { Authorization: "Bearer YOUR_TOKEN" },
    }
  );

  const wavBuffer = await response.arrayBuffer();
  // See Playback section above — the buffer is a self-describing WAV,
  // decode with AudioContext.decodeAudioData or play via `<audio>` + blob URL.
  ```
</RequestExample>

<ResponseExample>
  ```text 200 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <binary WAV audio stream>
  ```

  ```json 401 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "detail": "Missing Authorization header"
  }
  ```

  ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "detail": "Message not found"
  }
  ```

  ```json 502 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "detail": "Audio generation failed"
  }
  ```
</ResponseExample>
