Skip to main content

LiveKit Integration

The Estuary Unity SDK supports LiveKit as an optional transport for low-latency WebRTC voice. The public surface is the ILiveKitVoiceManager interface in the core Estuary namespace. The concrete implementation lives in a separate Estuary.LiveKit assembly that only compiles when the LiveKit Unity SDK is installed (the assembly is gated by the ESTUARY_LIVEKIT scripting define, set automatically when io.livekit.livekit-sdk is detected).

EstuaryManager creates and uses the manager internally -- you normally do not interact with it directly. Reach for it only when you need lip sync, custom mute logic, or other advanced integration.

ILiveKitVoiceManager

Namespace: Estuary

Access the active manager via:

ILiveKitVoiceManager liveKit = EstuaryManager.Instance.LiveKitManager;

Returns null if the LiveKit SDK is not installed. Check EstuaryManager.Instance.IsLiveKitEnabled first.

Properties

PropertyTypeAccessDescription
IsConnectedboolgettrue when connected to a LiveKit room
IsPublishingboolgettrue when the microphone track is publishing
IsMutedboolgettrue when the microphone is muted
IsBotAudioMutedboolgettrue when bot audio is muted (e.g., during interrupts)
CurrentRoomNamestringgetName of the current LiveKit room (null if not connected)
OutputVolumefloatget/setBot audio output volume (0–1). Applied to the bot AudioSource.
DebugLoggingboolget/setToggle verbose logs

Methods

MethodReturnsDescription
SetCoroutineRunner(MonoBehaviour runner)voidSet the MonoBehaviour used to run LiveKit coroutines
ConnectAsync(string url, string token, string roomName)Task<bool>Connect to a LiveKit room
DisconnectAsync()TaskLeave the room and clean up
StartPublishingAsync()Task<bool>Publish the microphone track
StopPublishingAsync()TaskUnpublish the microphone track
MuteAsync()TaskMute the microphone
UnmuteAsync()TaskUnmute the microphone
ToggleMuteAsync()TaskToggle mute state
SignalInterruptAsync(string messageId = null, float interruptedAt = 0f)TaskNotify the server to stop streaming TTS and immediately mute bot audio
MuteBotAudio(bool muted)voidMute/unmute the bot's audio track locally (volume-based)
NotifyAudioChunk(string messageId, float timestamp = 0f)boolTrack an incoming audio chunk; returns false if the chunk should be discarded
ProcessMainThreadQueue()voidDrain queued events onto the Unity main thread (called by EstuaryManager.Update)
PrewarmRoom()voidPre-create the LiveKit Room instance to save allocation time on connect
GetRoom()objectGet the underlying LiveKit Room (treat as opaque -- consumers should cast inside the Estuary.LiveKit assembly)

Events

EventSignatureDescription
OnConnectedAction<string>Connected to the room (room name)
OnDisconnectedAction<string>Disconnected from the room (reason)
OnErrorAction<string>Connection or publishing error
OnMuteStateChangedAction<bool>Microphone mute state changed (true = muted)
OnBotAudioSourceCreatedAction<AudioSource>Bot's AudioSource created at runtime (use for lip sync)

Connection Flow

1. EstuaryManager calls EstuaryClient.RequestLiveKitTokenAsync()
2. Server responds with livekit_token (JWT, URL, room name)
3. EstuaryManager calls ILiveKitVoiceManager.ConnectAsync(url, token, room)
4. Manager connects to the room → OnConnected fires
5. EstuaryManager calls EstuaryClient.NotifyLiveKitJoinedAsync()
6. Server joins the bot to the room and emits livekit_ready
7. EstuaryManager.LiveKitState transitions: WaitingForBot → Ready
8. The manager subscribes to the bot's audio track
9. OnBotAudioSourceCreated fires with the runtime AudioSource

Interrupt Handling

When SignalInterruptAsync is called:

  1. The server is notified via client_interrupt
  2. Bot audio is muted locally by setting the bot AudioSource volume to 0 (preserves the audio pipeline)
  3. The interrupted messageId and timestamp are recorded
  4. Subsequent audio chunks for the interrupted message (or with stale timestamps) are discarded by NotifyAudioChunk
  5. When a new message arrives with a different messageId, bot audio is unmuted automatically

Optional Dependency

The LiveKit integration is optional. The Estuary SDK's text-only features work without LiveKit installed.

PackageVersionPurpose
io.livekit.livekit-sdk1.3.3+WebRTC voice transport

Install via the Package Manager:

https://github.com/livekit/client-sdk-unity.git#v1.3.3

The Estuary SDK ships with an Editor-only auto-installer that detects a missing LiveKit SDK on domain reload and offers to install it via UPM. When LiveKit is not installed, EstuaryManager.IsLiveKitEnabled returns false, LiveKitManager is null, and the SDK gracefully falls back to WebSocket-only behavior.

When LiveKit is installed, Unity automatically defines the ESTUARY_LIVEKIT scripting symbol via versionDefines, which compiles the Estuary.LiveKit assembly containing the concrete LiveKitVoiceManager, microphone sources, and registrar.