Sync LiveKit rooms, participants, tracks, egress, and ingress into Convex reactively via webhooks, and manage them directly from Convex actions.
npm install convex-livekitconvex-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.
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.
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).
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.
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.
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.
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.
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.
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.
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.