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

# LiveKit integration

> Add Coda WebSocket v1 to a LiveKit agent, configure the plugin, and test local audio playback.

Set `websocket_url="wss://api.rime.ai/coda/ws"` in `rime.TTS` to use Coda WebSocket v1. The plugin handles authorization, message encoding, sentence buffering, audio decoding, and connection reuse.

## Install the plugin

Use Python 3.11 or later and [uv](https://docs.astral.sh/uv/getting-started/installation/). Set `RIME_API_KEY` in your server's environment. The plugin sends this key to the selected endpoint.

Use `livekit-plugins-rime` version `1.8.2` or later. [LiveKit Agents 1.8.2](https://github.com/livekit/agents/releases/tag/livekit-agents%401.8.2) introduced Coda WebSocket v1 support, including both JSON and binary protocols. Earlier plugin versions do not accept `websocket_url` or `websocket_protocol`.

These commands create a project and install the LiveKit Rime plugin:

```bash theme={null}
uv init --python 3.11 coda-livekit
cd coda-livekit
uv add 'livekit-plugins-rime>=1.8.2'
```

For an existing project, run the same `uv add` command in its directory to update the dependency requirement. The plugin installs compatible `livekit-agents` and `rime-api` dependencies. Commit your `uv.lock` file so deployments use the same dependencies.

## Use the plugin in an agent session

Pass `rime.TTS` to your `AgentSession`. This example assumes the agent already supplies speech recognition and an LLM. Omit `model` because `/coda/ws` selects Coda; supplying both raises `ValueError`.

```python theme={null}
from livekit.agents import AgentSession
from livekit.plugins import rime

session = AgentSession(
    tts=rime.TTS(
        websocket_url="wss://api.rime.ai/coda/ws",
        websocket_protocol="binary",
        speaker="lyra",
        lang="en",
    ),
)
```

The plugin defaults to binary. Set `websocket_protocol="json"` to use JSON. Both modes support streaming through `session.say()` and streamed LLM replies. Do not add a `tts.StreamAdapter`.

For room setup, speech recognition, and an LLM, follow the [LiveKit agent quickstart](/docs/quickstart-livekit), then use the TTS configuration above.

## Run the audio demo

[Download the audio demos](/files/coda-audio-demos.zip), extract the archive, and open its `coda-audio-demos` directory. With `RIME_API_KEY` set and a local audio output device available, run:

```bash theme={null}
uv run stream_livekit.py
```

The demo plays audio as frames arrive, then prints `Playback complete`. It needs no LiveKit room, speech recognition provider, or LLM. To test JSON, run `RIME_WEBSOCKET_PROTOCOL=json uv run stream_livekit.py`. The included README covers audio-device setup and troubleshooting.

For direct plugin calls, use `stream()`; the WebSocket provider's `synthesize()` method raises an error. Call `end_input()` to finish input, then keep reading until synthesis ends. Both encodings produce decoded PCM frames.

## Plugin parameters

These settings apply to both encodings:

| Plugin option        | Default                                                | Behavior or wire field                                                                                                        |
| -------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `websocket_url`      | Required to select v1                                  | Full endpoint. `/coda/ws` selects Coda from the path.                                                                         |
| `websocket_protocol` | `"binary"`                                             | `"binary"` selects `rime.v1.binary`; `"json"` selects `rime.v1.json`.                                                         |
| `speaker`            | `"lyra"` for Coda                                      | `start.speaker`. Choose a [Coda voice](/docs/voices-coda).                                                                    |
| `lang`               | `"eng"`                                                | `start.language`. Set `"en"` or another supported BCP 47 tag explicitly.                                                      |
| `audio_format`       | `"audio/pcm"`                                          | `start.audioParameters.audioFormat`. Accepts the six [canonical MIME types](/api-reference/coda/websockets#audio-parameters). |
| `sample_rate`        | `24000` for Coda                                       | `start.audioParameters.samplingRate`. Set `8000` for 8 kHz telephony.                                                         |
| `time_scale_factor`  | Omitted; engine default `1.0`                          | `start.audioParameters.timeScaleFactor`. Below `1` is faster; above `1` is slower.                                            |
| `api_key`            | `RIME_API_KEY` environment variable                    | Bearer credential in the upgrade header.                                                                                      |
| `tokenizer`          | Blingfire sentence tokenizer with `min_sentence_len=1` | Local text buffering. Custom tokenizers must emit complete sentences or stable clauses.                                       |
| `http_session`       | LiveKit-managed session                                | Outside an agent runtime, supply an `aiohttp.ClientSession` and close it yourself.                                            |

For 8 kHz mu-law, set both `audio_format="audio/pcmu"` and `sample_rate=8000`. The format alone leaves Coda at 24 kHz. The plugin decodes mu-law to 16-bit PCM at the selected rate.

### Supported settings

With `websocket_url`, do not supply `base_url`, `use_websocket=True`, `segment`, `reduce_latency`, `speed_alpha`, or generation controls such as `temperature`. These select or configure older interfaces and the adapter rejects them. Use `time_scale_factor` for speed.

The adapter does not expose `splitStrategy`, `config.defaults`, or `codaParameters.textLookaheadTokens`. Use a [direct client](/api-reference/coda/websockets-json) if your application needs these fields. It does not provide aligned word timestamps.

## Stream lifecycle

One LiveKit stream uses one Coda context. The adapter opens the context when the first non-empty sentence is ready and uses a pooled connection that has already received `ready`.

| LiveKit action                      | Adapter behavior                                                                         |
| ----------------------------------- | ---------------------------------------------------------------------------------------- |
| `speech.prewarm()`                  | Open a pooled connection before the first turn. Call from a running async context.       |
| `stream.push_text(text)`            | Buffer fragments locally. Send complete sentences as `text`, after an empty `start`.     |
| `stream.flush()`                    | Release the local tokenizer buffer as `text`. Keep the same context open for more input. |
| `stream.end_input()`                | Drain final text and send `end`. Continue to receive audio until `done`.                 |
| `stream.aclose()` before completion | Send `cancel` and drain the terminal response. Discard the connection if cleanup fails.  |
| `speech.aclose()`                   | Close tracked streams and pooled sockets.                                                |

Call `flush()` only at a complete sentence or stable clause boundary. It can release incomplete buffered text, and there is no server-side `flush` operation. An input pause needs no message. Only `end_input()` finishes normal input.

* Sequential turns reuse pooled connections. Concurrent LiveKit streams use separate sockets.
* `speech.update_options(...)` changes settings for later streams; active streams retain their initial settings.
* The plugin checks the subprotocol, `ready.protocol`, context IDs, and event order. It discards connections after malformed responses or failed cancellation cleanup.
* Set connection and terminal timeouts with `speech.stream(conn_options=...)` using LiveKit's `APIConnectOptions`.
