> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://murf.ai/api/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://murf.ai/api/docs/_mcp/server.

When you stream text over WebSockets, it arrives in pieces, often a few tokens at a time from an LLM. This page covers two features that control what Falcon does with that text:

* **Predictive chunking** decides when Falcon has enough text to start speaking. Use it to give up a little speed for more natural speech, or a little naturalness for speed.
* **Word timestamps** give you the start and end time of every spoken word, so you can tell what the user had heard when they interrupt.

> **Note**
>
> Every setting on this page goes at the top level of the frame, next to `text`.
> If you put one inside `voice_config`, Falcon ignores it and doesn't return
> an error or warning. Each setting also accepts a camelCase name:
> `predictiveChunking`, `minBufferSize`, `maxBufferDelayInMs` and
> `addWordTimestamps`.

## Predictive Chunking

Falcon synthesizes speech one sentence at a time. A full sentence gives the model enough context for natural rhythm and intonation. Falcon has to decide when each sentence ends, though, and the time it spends deciding adds to how long your user waits for audio.

`predictive_chunking` sets how quickly Falcon makes that decision.

| Value              | Behavior                                                                                  | Good for                                                              |
| ------------------ | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `strict` (default) | When a sentence ending is ambiguous, Falcon waits for one more character before deciding. | Narration, and text with a lot of times, abbreviations or titles      |
| `lenient`          | Falcon makes its best guess and starts synthesis straight away.                           | Voice agents and other real-time apps where quick turn-taking matters |

An ambiguous ending is one like `2 p.m.`, `the U.S.` or `Dr.`, where the period may or may not end the sentence. With `lenient`, Falcon will now and then split a sentence at one of these points, and you may hear a short pause there. Endings that aren't ambiguous are never delayed, whichever mode you pick.

```json
{
  "text": "Your appointment is at 2 p.m. tomorrow.",
  "predictive_chunking": "lenient",
  "context_id": "turn_1"
}
```

> **Tip**
>
> For a voice agent, start with `lenient`. You only need the buffer settings
> below if your text arrives with little or no punctuation.

> **Note**
>
> If you use a voice agent framework such as LiveKit or Pipecat, turn off its
> sentence tokenizer or text aggregation and stream LLM tokens straight to
> Falcon. When the framework splits text before Falcon does, you wait twice, and
> predictive chunking has little left to speed up. See
> [Best Practices](/api/docs/resources/best-practices#streaming-and-chunking).

### Buffer settings

Predictive chunking uses punctuation to find where sentences end. Some text arrives with very little punctuation, such as raw speech transcripts or some LLM output. When that happens, Falcon falls back on two buffer settings that decide when to send an unfinished sentence anyway.

If an LLM writes your text, the simpler fix is to make sure every sentence it writes ends with punctuation. The [Best Practices](/api/docs/resources/best-practices#streaming-and-chunking) page has a system prompt template that does this.

| Setting                  | Range             | Default | What it does                                            |
| ------------------------ | ----------------- | ------- | ------------------------------------------------------- |
| `min_buffer_size`        | 0–1000 characters | 100     | Sends the text once this many characters have built up  |
| `max_buffer_delay_in_ms` | 0–1000 ms         | 300     | Sends the text if nothing more arrives within this time |

Falcon sends an unfinished sentence as soon as it hits either limit.

Larger values give the model more context to work with, so speech sounds better. Smaller values get audio started sooner. Setting either value to `0` tells Falcon not to wait on that limit at all. With both at `0`, almost every chunk is synthesized the moment it arrives. That gives you the lowest Time to First Byte (TTFB), but each fragment is spoken as a separate utterance and the joins between them can sound choppy.

### Invalid values

| Setting                  | If you send                                             | What happens                                                                                           |
| ------------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `predictive_chunking`    | Anything other than `strict` or `lenient`               | You get warning `INVALID_PREDICTIVE_CHUNKING` and synthesis continues. Omit the field to use `strict`. |
| `min_buffer_size`        | A number outside 0–1000, or a value that isn't a number | You get warning `INVALID_BUFFER_SIZE` and the previous value is kept.                                  |
| `max_buffer_delay_in_ms` | A number outside 0–1000, or a value that isn't a number | You get warning `INVALID_BUFFER_DELAY` and the previous value is kept.                                 |

Both buffer settings accept numbers sent as strings, such as `"100"`. In your client, check `warning_code` rather than the message text, which can change. See [Errors & Warnings](/api/docs/text-to-speech/errors) for the full list.

### Example

Let's say the first chunk of text received is: "I just wanted to say that"

* This sentence is incomplete and has no punctuation, so Falcon doesn't immediately send it for audio generation.
* The current length is 24 characters, which is below the default `min_buffer_size` of 100 characters.
* Falcon waits for more input. If no additional text arrives within the time set by `max_buffer_delay_in_ms` (e.g., 500 ms), Falcon sends whatever text it has.

**Result:** After 500 ms, "I just wanted to say that" is sent for audio generation to avoid further delay. This mechanism ensures fast responses (good TTFB) without compromising too much on naturalness or context.

## Word Timestamps

With word timestamps on, Falcon tells you when each word starts and ends in the audio it sends. You can use them to work out what the user had heard when they interrupted.

Word timestamps work in every locale except Chinese, Japanese and Korean.

### Turning them on

Send `"add_word_timestamps": true`. The setting applies to the whole WebSocket connection.

```json
{
  "text": "Hello there.",
  "add_word_timestamps": true,
  "context_id": "turn_1"
}
```

### What you receive

Timestamps come in their own JSON frames, mixed in with the audio frames. They aren't part of the base64 `audio` field. Read them the same way you read `audio`, `final`, `error` and `warning` frames.

```json
{
  "context_id": "turn_1",
  "trace_id": "0f8bb0ef-8dcb-4815-8b3a-1e2d3c4b5a69",
  "timestamps": {
    "words": [
      {
        "word": "Hello",
        "start_s": 0.0,
        "end_s": 0.42,
        "start_frame": 0,
        "end_frame": 21
      }
    ]
  }
}
```

| Field                                 | Description                                                                      |
| ------------------------------------- | -------------------------------------------------------------------------------- |
| `context_id`                          | Same context as the matching audio frames                                        |
| `trace_id`                            | Same request ID as the matching audio frames                                     |
| `timestamps.words[].word`             | The spoken word                                                                  |
| `timestamps.words[].start_s`, `end_s` | When the word starts and ends, in seconds                                        |
| `start_frame`, `end_frame`            | Optional. The same positions counted in audio frames, when the engine sends them |

> **Note**
>
> The `word` field is normalized spoken text. Dates, numbers, acronyms,
> currencies and the like will come back differently from your input —
> `"$50"` as `"fifty dollars"`, `"2pm"` as `"two p m"`.

### How the timing works

Times are in seconds. The first sentence of each context starts at 0. Each later sentence picks up where the last word of the previous sentence ended. On barge-in, compare each timestamp's `start_s` to the current playback position to work out which words the user actually heard.

Audio is generated faster than real time, so a word's timestamp will be available before audio plays.

### Handling interruptions

When the user talks over the agent:

1. Stop playback.
2. Send a `clear` frame with that turn's `context_id`, so Falcon stops sending audio that's still queued. See [Context ID](/text-to-speech/web-sockets/context-id).
3. Drop any audio you've already received past the current playback position.
4. Drop any timestamps whose `start_s` is past that same position.

The timestamps you're left with match what the user actually heard.

## Best Practices

* Tune latency with `predictive_chunking` first. Use `lenient` for voice agents and `strict` when speech quality matters more than speed.
* If you use LiveKit or Pipecat, turn off the framework's sentence tokenizer or text aggregation so Falcon does all the splitting.
* Change the buffer settings only if your text has little or no punctuation.
* Keep every setting on this page at the top level of the frame, outside `voice_config`.
* On barge-in, cut audio and timestamps at the same playback position so you know exactly what the user heard.

## Next Steps

#### [Context ID](/text-to-speech/web-sockets/context-id)

Manage multiple turns and interruptions on one connection.

#### [Latency Optimization](/text-to-speech/latency)

Measure first-byte latency and bring it down.

#### [Errors & Warnings](/text-to-speech/errors)

Every error and warning code, with the cause and the fix.

#### [Best Practices](/api/docs/resources/best-practices#streaming-and-chunking)

How to write and stream text for Falcon in a voice agent, including an LLM
system prompt template.

## FAQs

#### Which setting should I change first to reduce latency?

Set `predictive_chunking` to `lenient`. Look at the buffer settings only if
your text arrives with little or no punctuation.

#### Does strict add latency to every sentence?

No. `strict` only waits when an ending is ambiguous, such as `2 p.m.` or
`Dr.`. Other sentence endings go through without delay.

#### My settings don't seem to have any effect. Why?

They're probably inside `voice_config`. Move them to the top level of the
frame, next to `text`.

#### I use LiveKit or Pipecat. Should I keep the framework's sentence splitting on?

No. Turn off the sentence tokenizer or text aggregation and stream LLM tokens
straight to Falcon. Falcon already waits for each sentence to end, so
splitting in the framework as well only adds delay.

#### Why am I not getting word timestamps?

Check that `add_word_timestamps`is passed as `true` and that your locale isn't Chinese, Japanese or Korean.