LiveKit Python SDKs
repository·main·Indexed 18 days ago
https://github.com/livekit/python-sdksA monorepo providing Python SDKs for building real-time video, audio, and data applications using WebRTC. It includes a real-time SDK for participants and a server API for administrative tasks such as room management and token generation. Key features include PlatformAudio for voice processing (AEC, NS, AGC), synthetic audio mode for programmatic generation, and AVSynchronizer for audio-video stream alignment.
What's inside livekit-python-sdks
- The LiveKit Python SDK allows you to integrate real-time video, audio, and data capabilities into Python applications using WebRTC. It is specifically designed to work with LiveKit Agents to build voice AI applications.
Authenticate `LiveKitAPI` (Backend vs Client-side)
mainYou can authenticate the
LiveKitAPIin two ways:- Backend (Recommended): Provide an
api_keyandapi_secret. This is suitable for server-side applications. - Client-side: Provide a pre-signed token using
LiveKitAPI.with_token(). This is used when you must not expose the API secret.
If no values are provided, the SDK falls back to the following environment variables:
LIVEKIT_URL,LIVEKIT_API_KEY,LIVEKIT_API_SECRET, andLIVEKIT_TOKEN.# API key & secret (backend) lkapi = api.LiveKitAPI("https://my-project.livekit.cloud", api_key="...", api_secret="...") # pre-signed token (client-side) lkapi = api.LiveKitAPI.with_token(my_token, "https://my-project.livekit.cloud")- Backend (Recommended): Provide an
How PlatformAudio works and when to use it
mainPlatformAudio uses WebRTC's Audio Device Module (ADM) for microphone capture. It is the recommended mode for most applications, especially voice and video calls.
Key Features:
- Built-in voice processing: Echo Cancellation (AEC), Noise Suppression (NS), and Auto Gain Control (AGC).
- Hardware acceleration on supported platforms.
- Automatic speaker playout for received audio.
- Device enumeration and selection.
Limitations:
- No direct access to raw audio frames (ADM sends directly to WebRTC).
- Cannot apply custom audio processing before publishing.
Usage Example:
platform_audio = rtc.PlatformAudio() source = platform_audio.create_audio_source( rtc.PlatformAudioOptions( echo_cancellation=True, noise_suppression=True, auto_gain_control=True, ) ) track = rtc.LocalAudioTrack.create_audio_track("microphone", source)Use RPC (Remote Procedure Call) between participants
mainRPC allows one participant to call a predefined method on another participant. This is useful for agent-to-client communication.
- Registering a method: The receiver uses
@room.local_participant.register_rpc_method(name)to define a handler. The handler receivesRpcInvocationDataand can return a response. - Performing a request: The caller uses
await room.local_participant.perform_rpc(...)specifying thedestination_identity,method, andpayload.
Note on Errors: If a handler raises an
RpcErrorwith a string message, that message is sent to the caller. Other unhandled errors arrive at the caller as code1500("Application Error").# Registering a method (Receiver side) @room.local_participant.register_rpc_method("greet") async def handle_greet(data: RpcInvocationData): print(f"Received greeting from {data.caller_identity}: {data.payload}") return f"Hello, {data.caller_identity}!" # Performing a request (Caller side) try: response = await room.local_participant.perform_rpc( destination_identity='recipient-identity', method='greet', payload='Hello from RPC!' ) print(f"RPC response: {response}") except Exception as e: print(f"RPC call failed: {e}")- Registering a method: The receiver uses
How Synthetic audio mode works and when to use it
mainSynthetic mode provides manual control over audio frames via
AudioSource.capture_frame(). Use this for programmatic audio generation or custom processing.Key Features:
- Full control over audio data and raw audio frames.
- Ability to generate synthetic audio (files, TTS, synthesis).
- Ability to apply custom filters, effects, or ML models.
Limitations:
- No built-in AEC/NS/AGC (must be implemented manually or via
AudioProcessingModule). - Must handle speaker playout manually via
AudioStream. - Requires external audio libraries (e.g.,
sounddevice,pyaudio) for microphone capture.
Usage Example:
source = rtc.AudioSource(sample_rate=48000, num_channels=1) track = rtc.LocalAudioTrack.create_audio_track("audio", source) frame = rtc.AudioFrame(data=audio_bytes, sample_rate=48000, ...) await source.capture_frame(frame)How AVSynchronizer works for video and audio synchronization
mainThe
AVSynchronizerutility maintains synchronization between video and audio streams. The core workflow involves pushing the initial synchronized video and audio frames together. Once initialized, subsequent frames are automatically synchronized based on the providedvideo_fpsand audio sample rate.To use it, instantiate
AVSynchronizerwith your sources and configuration, then useawait av_sync.push()for both video and audio frames.av_sync = AVSynchronizer( audio_source=audio_source, video_source=video_source, video_fps=30.0, video_queue_size_ms=100 ) # Push frames to synchronizer await av_sync.push(video_frame) await av_sync.push(audio_frame)Install the LiveKit Python SDK packages
mainThe LiveKit Python ecosystem is split into two primary packages depending on your use case:
livekit-api: Used for backend server operations, such as generating access tokens and managing rooms, egress, and ingress.livekit: The real-time SDK used by participants to connect to a room, publish/subscribe to tracks, and handle media.
Install the Server API:
$ pip install livekit-apiInstall the Real-time SDK:
$ pip install livekitpip install livekit-api pip install livekitAuthenticate with LiveKit Server APIs
mainThe
LiveKitAPIclass supports two authentication modes depending on your environment:- API key & secret (Backend): Recommended for server-side applications. The SDK uses your
LIVEKIT_API_KEYandLIVEKIT_API_SECRETto sign a short-lived token for every request. Never expose your API secret to a client. - Access token (Client-side): Used when you cannot expose the API secret. You must provide a pre-signed access token that already contains the necessary grants for the operations you intend to perform. The SDK sends this token verbatim.
Configuration follows a hierarchy: explicitly passed arguments take precedence over environment variables. The SDK falls back to the following environment variables if arguments are omitted:
LIVEKIT_URLLIVEKIT_API_KEYLIVEKIT_API_SECRETLIVEKIT_TOKEN
from livekit import api # Mode 1: API key & secret (Backend) # Uses LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET env vars lkapi = api.LiveKitAPI() # Or override env vars explicitly: lkapi = api.LiveKitAPI("https://my.livekit.host", api_key="api-key", api_secret="api-secret") # Mode 2: Pre-signed access token (Client-side) # Requires LIVEKIT_URL to be set in env vars, then pass the token lkapi = api.LiveKitAPI.with_token("a-pre-signed-token")- API key & secret (Backend): Recommended for server-side applications. The SDK uses your
Setup Local Video Packet-Trailer Examples
mainTo run the local video examples, you must first configure your LiveKit connection credentials using environment variables. Alternatively, you can pass these settings as command-line flags during execution.
Set the following environment variables:
export LIVEKIT_URL=https://your-livekit-host export LIVEKIT_API_KEY=your-api-key export LIVEKIT_API_SECRET=your-api-secretRun the examples from the repository root using
uv:uv run --project examples/local_video <command>export LIVEKIT_URL=https://your-livekit-host export LIVEKIT_API_KEY=your-api-key export LIVEKIT_API_SECRET=your-api-secretSet up LiveKit Python SDK environment variables
mainBefore running the examples, you must set the following environment variables to connect to your LiveKit server:
export LIVEKIT_URL=ws://localhost:7880 export LIVEKIT_API_KEY=devkey export LIVEKIT_API_SECRET=secretexport LIVEKIT_URL=ws://localhost:7880 export LIVEKIT_API_KEY=devkey export LIVEKIT_API_SECRET=secretManage local audio devices with `MediaDevices`
mainThe
rtc.MediaDevicesclass provides a high-level interface for audio I/O. It requires thesounddevicelibrary to be installed in your environment.Capturing Microphone Input
Use
devices.open_input()to open a microphone. You can enable Acoustic Echo Cancellation (enable_aec), noise suppression, high-pass filters, and auto-gain control. The resulting source can be used to create artc.LocalAudioTrackfor publishing.Playing Audio to Speakers
Use
devices.open_output()to create a player. You can add remote audio tracks to this player usingplayer.add_track(track)and then start playback withawait player.start().Full Duplex Audio
For effective echo cancellation in full duplex mode, open the input device with
enable_aec=Truefirst, then open the output device. The output player will automatically feed the APM's reverse stream back to the microphone input.from livekit import rtc # Capturing Microphone devices = rtc.MediaDevices() mic = devices.open_input(enable_aec=True, noise_suppression=True) track = rtc.LocalAudioTrack.create_audio_track("microphone", mic.source) await room.local_participant.publish_track(track) # Playing Audio player = devices.open_output() player.add_track(remote_audio_track) await player.start()Connect to a room using the Real-time SDK
mainTo participate in a live session, use
rtc.Room. You can listen to events likeparticipant_connectedandtrack_subscribed.When a video track is subscribed, you can create an
rtc.VideoStreamto process incoming frames. By default,autosubscribeis enabled, meaning the participant will automatically subscribe to all published tracks in the room.from livekit import rtc import asyncio import logging async def main(): room = rtc.Room() @room.on("participant_connected") def on_participant_connected(participant: rtc.RemoteParticipant): logging.info("participant connected: %s %s", participant.sid, participant.identity) async def receive_frames(stream: rtc.VideoStream): async for frame in stream: # process video frame here pass @room.on("track_subscribed") def on_track_subscribed(track: rtc.Track, publication: rtc.RemoteTrackPublication, participant: rtc.RemoteParticipant): logging.info("track subscribed: %s", publication.sid) if track.kind == rtc.TrackKind.KIND_VIDEO: video_stream = rtc.VideoStream(track) asyncio.ensure_future(receive_frames(video_stream)) await room.connect(URL, TOKEN) logging.info("connected to room %s", room.name) # Access existing participants and tracks for identity, participant in room.remote_participants.items(): print(f"identity: {identity}") for tid, publication in participant.track_publications.items(): print(f"\ttrack id: {publication}")