LiveKit Rust SDKs
repository·main·Indexed 19 days ago
https://github.com/livekit/rust-sdksThe LiveKit Rust SDK provides real-time video, audio, and data capabilities for Rust applications, enabling developers to connect to LiveKit Cloud or self-hosted servers. The repository includes the livekit and livekit-ffi crates, along with examples for agent dispatch, data tracks, text streaming, and local audio capture. It provides Docker-based build processes for x86_64 and AArch64 architectures to ensure binary compatibility with Linux distributions.
What's inside livekit-rust-sdks
- The LiveKit Rust Client SDK is a standalone, cross-platform SDK designed for Rust developers. It serves as a core foundation for other platform-specific SDKs (like Unity, iOS, and Android) by encapsulating signaling protocol logic and WebRTC business logic into a clean set of abstractions. This allows for consistent behavior across different platforms and frameworks.
Overview of the LiveKit Rust Client SDK
mainThe LiveKit Rust Client SDK is the official library for integrating real-time video, audio, and data features into Rust applications. It allows developers to connect to LiveKit rooms and participate in real-time multimedia sessions.Overview of LiveKit UniFFI
mainLiveKit UniFFI is an experimental FFI (Foreign Function Interface) using UniFFI. It is designed to expose core business logic that can be incrementally adopted by client SDKs.
Currently, it does not replace the existing
_livekit-ffi_interface but focuses on modularizing specific functionalities.Exposed Functionality:
- Logging
- Access token generation and verification
Overview of LiveKit FFI
mainLiveKit FFI provides Foreign Function Interface bindings for LiveKit. It is compiled as a dynamic library, which enables high-level client SDKs written in other languages to invoke APIs from the core
livekitRust crate. This architecture is used to power the following official client SDKs:- Python
- NodeJS
- Unity
Use the public LiveKit API instead of livekit-common
mainThe
livekit-commoncrate is an internal library containing shared data structures (such asParticipantIdentityorEncryptionType) used by other modules.Do not use this crate for building applications. Instead, use the public APIs provided by the
livekitcrate.Debug Rust code through Swift (UniFFI)
mainThe published
livekit-uniffi-xcframeworkis a release build with symbols stripped, meaning Xcode/lldb will only show Swift glue and bare memory addresses for Rust. To see full Rust stack traces, source listings, and variables, you must build a local debugxcframeworkthat contains full DWARF debug info.Key Requirements:
- Keep the
rust-sdkscheckout and itstarget/directory available. lldb resolves DWARF via OSO references into these object files. - Rebuild the xcframework after any Rust changes.
- Ensure the
xcframeworkis built for the target platform (e.g., macOS or iOS simulator).
Verification: You can check if a binary is debuggable by running:
nm -a <binary> | grep -c ' OSO '(A result > 0 indicates DWARF references are present; a stripped release build will return 0).- Keep the
Understand PlatformAudio FFI Handle Lifecycle and Reference Counting
mainThe
PlatformAudioFFI interface uses a reference-counting mechanism to manage the underlying Audio Device Module (ADM). Multiple FFI clients can create handles, but they all share the same underlying ADM instance.Lifecycle Rules
- Creation: The first call to
NewPlatformAudioRequesttriggers the creation and initialization of the Platform ADM and enables ADM recording. - Sharing: Subsequent calls to
NewPlatformAudioRequestincrement the internal reference count and reuse the existing ADM. - Termination: The ADM is only terminated and disabled when the reference count reaches zero (i.e., the last handle is released via
DisposeRequest).
Reference Counting Example
- Client A calls
NewPlatformAudioRequest()$\rightarrow$handle_1created (ref_count: 1). - Client B calls
NewPlatformAudioRequest()$\rightarrow$handle_2created (ref_count: 2). - Client A calls
DisposeRequest(handle_1)$\rightarrow$ (ref_count: 1). - Client B calls
DisposeRequest(handle_2)$\rightarrow$ (ref_count: 0, ADM disabled).
- Creation: The first call to
How to use Data Tracks in LiveKit
mainThe
livekit-datatrackcrate is an internal component used to power data track features within LiveKit client SDKs. It is not intended for direct use by application developers.To implement data track functionality in your application, you must use the public APIs provided by the official LiveKit client SDKs (such as the Rust SDK).
Understand Platform Audio Mode for VoIP
mainPlatform Audio Mode is used for dedicated VoIP applications that require direct access to the microphone and speakers, and need Acoustic Echo Cancellation (AEC). In this mode, the SDK manages the hardware via a platform-specific Audio Device Module (ADM).
Initialization Flow
PlatformAudio::new()is called.- The runtime acquires the platform ADM via
AdmProxy::AcquirePlatformAdm(), which increments the reference count and creates thewebrtc::AudioDeviceModuleif it's the first time. - Recording is enabled via
runtime.set_adm_recording_enabled(true). - Playout is enabled via
runtime.set_adm_playout_enabled(true).
Outbound Audio (Microphone to Network)
The Platform ADM captures microphone PCM data. This data is routed through
AudioStatetoAudioSendStreaminstances whereexternal=false(device sources). The audio is then encoded and sent over the network.Inbound Audio (Network to Speakers)
Decoded audio from the network flows through
AudioReceiveStreaminto theAudioMixer. Becauseplayout_enabledis true, theAdmProxy'sNeedMorePlayData()delegates the audio to theplatform_adm_, which plays the audio directly to the hardware speakers.Key Characteristics
- Platform ADM: Created and managed by the SDK.
- AEC Support: Acoustic Echo Cancellation works because the playout signal is routed through the ADM, providing the necessary reference signal.
- iOS Behavior:
AVAudioSessionis configured for VoIP mode.
How ADM Reference Counting works for shared audio resources
mainThe
AdmProxyuses a reference counting pattern to manage the lifecycle of the Platform ADM. This allows multiple clients (e.g., different FFI handles or multiple users in a single application) to share the same hardware audio resources without redundant initialization or premature termination.- Single User:
PlatformAudio::new()increments the ref count to 1 and creates the ADM.drop(audio)decrements it to 0 and terminates the ADM. - Multiple Users: If
audio1is active andaudio2 = PlatformAudio::new()is called, the ref count becomes 2. The ADM is reused. The ADM is only terminated when the last active handle is dropped. - FFI Clients (Unity/Python): Multiple handles (e.g., from different Unity clients) increment the
platform_adm_ref_count_. A separate process (like a Python agent) using aNativeAudioSourcedoes not interact with theplatform_adm_and thus operates in Synthetic Mode, even if Unity clients have activated Platform Mode.
Reference Counting Examples SCENARIO 1: Single User ════════════════════════ Time ──────────────────────────────────────────────────────────▶ ┌──────────────────────┐ ┌──────────────────────┐ │ PlatformAudio::new() │ │ drop(audio) │ │ ref_count: 0 → 1 │ │ ref_count: 1 → 0 │ │ CREATE Platform ADM │ │ TERMINATE Platform │ └──────────┬───────────┘ └──────────┬───────────┘ │ │ ▼ ▼ ═══════════╪═════════════════════════════════════════╪═══════════ Synthetic │ Platform Mode Active │ Synthetic │ │ SCENARIO 2: Multiple Users (Shared ADM) ═════════════════════════════════════════ Time ──────────────────────────────────────────────────────────▶ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ audio1 = │ │ audio2 = │ │ drop(audio1│ │ drop(audio2│ │ new() │ │ new() │ │ │ │ │ │ ref: 0→1 │ │ ref: 1→2 │ │ ref: 2→1 │ │ ref: 1→0 │ │ CREATE │ │ (reuse) │ │ (still │ │ TERMINATE │ │ ADM │ │ │ │ active) │ │ ADM │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ │ ▼ ▼ ▼ ▼ ════╪═════════════════╪═════════════════╪═════════════════╪══════ Synth │ Platform Mode Active │ │ Synth │ │ │ audio2 still │ │ │ works! SCENARIO 3: FFI Clients (Unity/Python) ═════════════════════════════════════════ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Unity Client A │ │ Unity Client B │ │ Python Agent │ │ │ │ │ │ │ NewPlatformAudio│ │ NewPlatformAudio│ │ Uses Native │ │ Request │ │ Request │ │ AudioSource │ │ handle_1 │ │ handle_2 │ │ (no PlatformAdm)│ └────────┬────────┘ └────────┬────────┘ └─────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ AdmProxy │ │ │ │ platform_adm_ref_count_ = 2 (from Unity clients) │ │ │ │ Both Unity clients share the same Platform ADM. │ │ Python agent uses synthetic mode (NativeAudioSource). │ │ │ │ When both Unity clients call DisposeRequest: │ │ handle_1 dispose → ref_count = 1 │ │ handle_2 dispose → ref_count = 0 → TERMINATE │ └─────────────────────────────────────────────────────────────────┘- Single User:
Authenticate the LiveKit Server API
mainThe server API supports two authentication modes depending on your use case:
API key & secret (Backend use): Recommended for server-side applications.
- Use
LiveKitApi::new(host)to automatically read credentials from theLIVEKIT_API_KEYandLIVEKIT_API_SECRETenvironment variables. - Use
LiveKitApi::with_api_key(host, key, secret)to provide credentials explicitly. - A short-lived token is signed for each request automatically.
- Use
Access token (Client-side use): Use this when you must not expose the API secret.
- Use
LiveKitApi::with_token(host, token)to send a pre-signed access token verbatim. Ensure the token's grants cover the intended API calls.
- Use
Configure Audio Recording and Playout Gates
mainThe
AdmProxyuses gates to control how the platform ADM behaves when it is active. These gates determine if the hardware is actually accessed.Gate Default Behavior when truerecording_enabled_falseInitializes and starts microphone capture via the platform ADM. playout_enabled_falseRoutes remote audio through platform speakers and enables AEC. Note on Default Behavior: When
playout_enabled_isfalse, the SDK enters Synthetic Playout Mode. In this mode, the WebRTC pipeline stays alive by running a periodic task (every 10ms) that pulls audio data viaNeedMorePlayData, which is then delivered to your application via FFI callbacks (e.g.,NativeAudioStream).