Convex LiveKit

Sync LiveKit rooms, participants, tracks, egress, and ingress into Convex reactively via webhooks, and manage them directly from Convex actions.

Installation

npm install convex-livekit

About Convex LiveKit

convex-livekit syncs LiveKit room, participant, and egress state into Convex tables via verified webhooks, making that data available to reactive queries. It also provides Convex actions for room management (create, delete, update metadata, remove participants) and JWT token minting for client authentication. The component's tables are isolated in their own schema and are only accessible through the functions the component exposes.

Benefits

Use cases

how to sync LiveKit room state with a Convex database reactively

convex-livekit mounts a webhook handler on your Convex HTTP router that receives and cryptographically verifies LiveKit webhook events. Each event updates isolated Convex tables for rooms, participants, tracks, egress, and ingress, so useQuery in your React app re-renders automatically as rooms open, participants join, and tracks are published without any polling.

how to generate a LiveKit access token from a Convex function

The LiveKit client exposes a createRoomToken method that signs a short-lived JWT using your API key and secret. It touches no database, so it works from a Convex query or action. Pass the returned token directly to a LiveKit client SDK via room.connect(url, token).

how to start and stop room recording in LiveKit from a backend

convex-livekit provides startRoomCompositeEgress and stopEgress actions that call LiveKit's StartRoomCompositeEgress RPC and immediately patch the corresponding egress row in Convex. This means recording status is visible in reactive queries without waiting for the egress_started or egress_ended webhook to arrive.

how to bring an RTMP stream into a LiveKit room as a participant

The createIngress action provisions an RTMP, WHIP, or pulled-URL endpoint and returns an ingressId, url, and streamKey. The external encoder joins the room as a regular participant, and ingress_started and ingress_ended webhook events keep the ingress state synced in Convex so you can query live buffering, publishing, or error status.

Frequently asked questions

Does convex-livekit add tables to my app's Convex schema?

No. convex-livekit is a Convex component, so its rooms, participants, tracks, egress, ingress, and webhookEvents tables live in an isolated schema separate from your app's schema. They are only accessible through the functions the component exposes, not through your app's direct database queries.

How does convex-livekit verify incoming LiveKit webhooks?

convex-livekit verifies every inbound webhook by checking the signed JWT's signature, issuer, expiry, and a body-hash claim before writing anything to the database. This matches LiveKit's own webhook verification scheme and uses your existing LiveKit API key and secret, so no separate webhook secret is required.

What happens to participant state when a client disconnects unexpectedly?

convex-livekit handles participant_connection_aborted events the same way it handles a clean participant_left event. The participant row in Convex is updated immediately, so useQuery consumers see the departure regardless of whether the disconnect was clean or abrupt.

Does convex-livekit work with self-hosted LiveKit servers?

Yes. The LiveKit client is initialized with a host parameter that accepts any LiveKit server URL, including self-hosted deployments. You set LIVEKIT_API_KEY, LIVEKIT_API_SECRET, and LIVEKIT_HOST as Convex environment variables pointing at your server, and register the webhook URL on your self-hosted server's webhook config instead of LiveKit Cloud settings.

Can I track whether a participant's camera or microphone is active, not just whether they are in the room?

Yes. convex-livekit handles track_published and track_unpublished webhook events and stores each track's source (camera, microphone, screen share), muted snapshot, and type in a separate tracks table. You can query this table reactively to determine whether a specific participant's mic or camera is currently live.

Links