LiveKit Python SDKs

repository·main·Indexed 18 days ago

https://github.com/livekit/python-sdks

A 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.

Tokens
7.2K
Snippets
25
Records
31
Agent score
63%

What's inside livekit-python-sdks

  1. Authenticate `LiveKitAPI` (Backend vs Client-side)

    main

    You can authenticate the LiveKitAPI in two ways:

    1. Backend (Recommended): Provide an api_key and api_secret. This is suitable for server-side applications.
    2. 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, and LIVEKIT_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")
  2. How PlatformAudio works and when to use it

    main

    PlatformAudio 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)
  3. Use RPC (Remote Procedure Call) between participants

    main

    RPC allows one participant to call a predefined method on another participant. This is useful for agent-to-client communication.

    1. Registering a method: The receiver uses @room.local_participant.register_rpc_method(name) to define a handler. The handler receives RpcInvocationData and can return a response.
    2. Performing a request: The caller uses await room.local_participant.perform_rpc(...) specifying the destination_identity, method, and payload.

    Note on Errors: If a handler raises an RpcError with a string message, that message is sent to the caller. Other unhandled errors arrive at the caller as code 1500 ("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}")
  4. How Synthetic audio mode works and when to use it

    main

    Synthetic 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)
  5. How AVSynchronizer works for video and audio synchronization

    main

    The AVSynchronizer utility 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 provided video_fps and audio sample rate.

    To use it, instantiate AVSynchronizer with your sources and configuration, then use await 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)
  6. Install the LiveKit Python SDK packages

    main

    The LiveKit Python ecosystem is split into two primary packages depending on your use case:

    1. livekit-api: Used for backend server operations, such as generating access tokens and managing rooms, egress, and ingress.
    2. 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-api

    Install the Real-time SDK:

    $ pip install livekit
    pip install livekit-api
    pip install livekit
  7. Authenticate with LiveKit Server APIs

    main

    The LiveKitAPI class supports two authentication modes depending on your environment:

    1. API key & secret (Backend): Recommended for server-side applications. The SDK uses your LIVEKIT_API_KEY and LIVEKIT_API_SECRET to sign a short-lived token for every request. Never expose your API secret to a client.
    2. 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_URL
    • LIVEKIT_API_KEY
    • LIVEKIT_API_SECRET
    • LIVEKIT_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")
  8. Setup Local Video Packet-Trailer Examples

    main

    To 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-secret

    Run 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-secret
  9. Set up LiveKit Python SDK environment variables

    main

    Before 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=secret
    export LIVEKIT_URL=ws://localhost:7880
    export LIVEKIT_API_KEY=devkey
    export LIVEKIT_API_SECRET=secret
  10. Manage local audio devices with `MediaDevices`

    main

    The rtc.MediaDevices class provides a high-level interface for audio I/O. It requires the sounddevice library 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 a rtc.LocalAudioTrack for publishing.

    Playing Audio to Speakers

    Use devices.open_output() to create a player. You can add remote audio tracks to this player using player.add_track(track) and then start playback with await player.start().

    Full Duplex Audio

    For effective echo cancellation in full duplex mode, open the input device with enable_aec=True first, 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()
  11. Connect to a room using the Real-time SDK

    main

    To participate in a live session, use rtc.Room. You can listen to events like participant_connected and track_subscribed.

    When a video track is subscribed, you can create an rtc.VideoStream to process incoming frames. By default, autosubscribe is 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}")