livekit-plugins-slng adds STT and TTS adapters for LiveKit Agents. It connects through SLNG’s Unmute Bridge, so models on the SLNG platform work with the same code: pass a model identifier and the plugin builds the endpoint itself.
The plugin is realtime WebSocket only. Models that expose only HTTP endpoints (for example batch STT models such as sarvam/saaras:v3 or slng/speechmatics/batch) are not available through it; check the Models catalog for streaming support.
This page documents plugin version 1.6.7 and later, a major rewrite
distributed through the official LiveKit Agents repository. If you are
upgrading from 1.6.6 or earlier, read Migrating from earlier
versions first: several parameters
changed or were removed.
Prerequisites
- Python 3.10+
livekit-agents>=1.6.10- A LiveKit Agents project
- An SLNG key (get one at app.slng.ai)
Installation
Credentials
The plugin reads your SLNG key from theSLNG_API_KEY environment variable automatically:
api_key:
slng.STT also accepts a legacy api_token= alias, but it is deprecated.
Use api_key in new code.Quickstart
Create an STT and TTS instance, then pass them to your LiveKit agent session:wss://api.slng.ai/v1/bridges/unmute/{stt|tts}/<model>) by itself.
Lower STT turn latency
For the lowest end-of-turn latency, let the plugin know when the user stops speaking. The plugin then sends a finalize signal so the provider returns the final transcript immediately instead of waiting for its own endpointing:Full voice agent example
This example wires up STT, TTS, and VAD into a complete LiveKit agent that greets the user on join:Model identifiers
Models follow the formatprovider/model:variant. Prefix with slng/ to target an SLNG-hosted instance:
STT reference
slng.STT streams speech-to-text over WebSocket through the Unmute Bridge.
Constructor
model or connections must be provided; there is no default model. Any additional keyword argument is forwarded to the bridge init payload; the bridge applies the options the selected model’s catalog declares and ignores the rest, so option names must match that model’s contract (for example Deepgram consumes endpointing and smart_format). The generic VAD and diarization options apply only to models that declare those fields.
TTS reference
slng.TTS streams text-to-speech over WebSocket through the Unmute Bridge.
Constructor
voice is required and passed verbatim as the provider’s voice identifier (use the provider’s voice ID, not a display name). Additional keyword arguments are forwarded to the bridge init payload according to the selected model’s contract, for example Rime Arcana speakingStyle, Sarvam Bulbul pace, or Cartesia Sonic emotion. You can also pass pronunciation={"mode": "rewrite", "name": "my-dictionary"} to apply a pronunciation dictionary.
You can change voice, language, and speed at runtime with tts.update_options(...); the change propagates to failover candidates and safely replaces any pre-opened standby connection.
runtime_init is an advanced option for integrations that drive the bridge session themselves: when set, it is sent as the init payload instead of the one the plugin builds from model, voice, language, and the other options. Most clients can ignore it.
Text chunking
text_chunking controls how streamed text is sent to the provider. The default "auto" batches words into phrases (flushing at punctuation or phrase_max_chars), which avoids the choppy audio and slow completions that word-by-word streaming causes on some providers. Set "word" only if you specifically need per-word forwarding.
Warm standby connections
By default, each spoken turn opens a fresh connection, which adds connection setup time to the first audio of every turn. Withwarm_standby_enabled=True, the plugin pre-opens the next connection in the background while the current turn is playing, so the next turn starts on a connection that is already open all the way to the provider. Time-to-first-audio then drops to roughly the provider’s generation time:
- The standby is a single connection per TTS instance (it never accumulates), and it counts toward your concurrency limit while it waits.
- If the prepared connection expires during a long user silence, the plugin automatically reconnects for that turn at regular latency. No error surfaces.
- Some providers close idle connections after a short window, which limits how long a prepared connection survives silence. Where the provider exposes an inactivity option in its model contract, pass it as a model option to keep the standby alive through natural pauses in conversation.
Streaming vs batch
tts.stream()streams text and returns audio chunks in real time. Use this for voice agents.tts.synthesize(text)does one-shot synthesis over the same bridge connection. Works well for previews and static prompts.
Voice selection
Pick a voice that matches your chosen model. See the Voices pages for what’s available per provider.Failover
BothSTT and TTS accept connections=[...], an ordered list of candidates. Candidates may be model identifiers, Unmute Bridge endpoint URLs, or typed connection configurations. A model is not needed when connections supplies the complete list:
- Each candidate gets
APIConnectOptions.max_retryattempts before the next candidate is selected. - Deterministic client errors (most 4xx statuses) skip the retries and advance to the next candidate immediately.
- HTTP 413 (payload too large) is terminal: every candidate would reject the same oversized request, so the error surfaces without walking the chain.
- STT fails over at safe stream boundaries and replays buffered audio (including a pending finalize) onto the new connection, so no speech is lost mid-utterance.
- TTS switches only before its first audio. All TTS candidates must use the same sample rate and channel count.
- After
fallback_recovery_cooldown_s(60 seconds by default), the primary is tried again on the next request or utterance. - With a single candidate, a transient mid-utterance connection drop reconnects the same endpoint and replays the buffered audio instead of ending the stream.
STTConnectionConfig and TTSConnectionConfig keep endpoint-specific headers, init payloads, and voices together:
Bring your own key (BYOK)
Passprovider_api_key to use your own provider credential. The plugin sends it as the X-Slng-Provider-Key header, and the gateway forwards it to the upstream provider. External (third-party) models only; see BYOK for details:
Region override
BothSTT and TTS accept region_override, which maps to the gateway’s X-Region-Override header. Pass a single region or a list of preferred regions in priority order:
world_part_override (for example "eu"), which maps to the gateway’s X-World-Part-Override header. region_override takes precedence when both are set. See Region override for accepted values.
Tracking IDs
external_agent_id and external_session_id attach your own identifiers to SLNG usage events (as the X-SLNG-Agent-Id and X-SLNG-Session-Id headers), so you can correlate gateway usage with your own analytics. Both are optional, max 128 characters.
Plugin events
Subscribe toslng_event for typed events covering gateway session identifiers and failover activity:
gateway.session (the gateway request and session IDs for each connection) and fallback.attempt_failed, fallback.switch_succeeded, fallback.primary_recovered, and fallback.exhausted for failover monitoring.
Migrating from earlier versions
Version 1.6.7 is a breaking rewrite of the plugin:- All traffic goes through the Unmute Bridge.
model_endpointandmodel_endpointswere removed and now raise an error; pass a model identifier (model="deepgram/nova:3") orconnections=[...]instead. - STT no longer defaults to
model="deepgram/nova:3"; pass a model (orconnections) explicitly. - TTS
voiceis required and passed verbatim as the provider’s voice identifier (use the provider’s voice ID, not a display name). - Language codes are no longer normalized client-side; send the value the model expects (for example BCP-47
hi-INfor Sarvam Bulbul, nothi). - STT
recognize()(HTTP batch) is no longer supported; usestream(). Onlypcm_s16leinput audio is supported. api_tokenstill works on STT but is deprecated; useapi_key.- Provider-specific defaults (voice normalization, implicit fallbacks) were removed; configure candidates explicitly via
connections.
The plugin registers itself with LiveKit on import and outputs
linear16
PCM audio. Both STT and TTS authenticate with api_key.Next steps
- Browse available Models for STT and TTS
- Check the Voices pages for voice options per provider
- See Voice Agents for the SLNG-managed agents API