node-sdks

The official Node.js realtime SDK for LiveKit, giving server-side apps a typed client for audio, video, data streams, and RPC over WebRTC.

SDK
npm
v0.13.34
284stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
84/100Excellent
Development Activity88
Maintenance92
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture78
Code Quality74
Innovation68
Learning Curve55

@livekit/rtc-node is LiveKit’s Node.js binding for building realtime applications on top of its WebRTC-based infrastructure. It lets a server-side Node process join a LiveKit room as a first-class participant: publishing and subscribing to audio/video tracks, exchanging structured byte/text data streams, performing participant-to-participant RPC calls, and managing end-to-end encryption, all from plain TypeScript.

Rather than reimplementing WebRTC in JavaScript, the package is a thin, idiomatic wrapper around a native FFI core shared across LiveKit’s SDK family (the same low-level bridge backs LiveKit’s Python and other language clients). Domain objects like Room, LocalParticipant, AudioSource, and VideoStream translate familiar EventEmitter-style calls into protobuf-encoded requests sent across that native boundary, then surface the resulting events back as typed callbacks.

It is the natural building block for server-side LiveKit integrations: recording and compositing agents, headless bots that publish synthesized audio/video into a room, webhook-driven automation, or any backend service that needs to sit inside a LiveKit session without a browser.

What You Get

  • A Room client with connect/disconnect lifecycle, typed RoomEvent callbacks, and access to local and remote participants
  • Audio and video publishing primitives (AudioSource, VideoSource, track publication options) for feeding synthesized or captured media into a room
  • Audio/video subscription streams (AudioStream, VideoStream) for consuming other participants’ published tracks
  • A typed data-streams API for sending and incrementally reading byte and text streams over the data channel
  • Participant-to-participant RPC (registerRpcMethod / performRpc) for invoking application-defined methods across the room
  • End-to-end encryption management via E2EEManager, FrameCryptor, and pluggable KeyProviders

Common Use Cases

  • Building server-side voice/video agents that join a LiveKit room and process or generate media in real time
  • Recording, compositing, or forwarding published tracks from a headless Node service
  • Bridging LLM function calls between a backend and connected clients using the RPC layer
  • Piping structured data (transcripts, control messages, telemetry) between participants via data streams
  • Automating room lifecycle actions (dispatch, cleanup, moderation) from backend webhooks

Under The Hood

Architecture The package is a thin TypeScript wrapper around a native FFI layer (@livekit/rtc-ffi-bindings) that bridges to a compiled Rust core shared across LiveKit’s SDK family. A singleton FfiClient (src/ffi_client.ts) extends a typed EventEmitter, sending protobuf-encoded FfiRequest messages across the native boundary and correlating async FfiEvent responses back to callers. Domain objects — Room, LocalParticipant/RemoteParticipant, AudioSource/AudioStream, VideoSource/VideoStream, E2EEManager, and the data-stream readers/writers — all proxy their method calls through this same FfiClient.request() plumbing rather than implementing WebRTC logic themselves. This keeps the actual media pipeline in native code while exposing an idiomatic, event-driven Node API on top; because every wrapper depends on the same shared low-level protobuf schema, a breaking change to that FFI contract ripples across the whole package at once.

Tech Stack Written in strict TypeScript (strict mode, noUncheckedIndexedAccess, isolatedModules, verbatimModuleSyntax) targeting Node 18+, built with tsup into dual ESM/CJS output, and managed inside a pnpm-workspace/Turborepo monorepo alongside sibling packages like livekit-server-sdk. It depends on @livekit/rtc-ffi-bindings for the native protobuf/FFI glue, @livekit/mutex and @livekit/typed-emitter for concurrency-safe locking and typed event emitters, pino/pino-pretty for structured logging, and @datastructures-js/deque for internal queueing. Tests run on Vitest, with GitHub Actions workflows covering CI, a dedicated test-API check, and dependency pin verification.

Code Quality Unit tests cover the audio pipeline (mixer, source), async queue, and general utilities, complemented by dedicated end-to-end tests that exercise real room connections and data-stream flows under src/tests. Errors are surfaced through typed exception classes (ConnectError, RpcError) rather than raw strings or swallowed failures, and the typed EventEmitter wrappers catch mismatched event names or payloads at compile time. Strict TypeScript settings and a project-wide ESLint configuration enforced in CI provide a solid quality floor, though test coverage is concentrated on a handful of modules rather than exhaustively exercising every wrapper class.

API Design The SDK hides all of the async FFI request/event correlation behind a conventional-feeling Node API — await room.connect(...) and .on(RoomEvent.TrackSubscribed, ...) read like a plain JavaScript class despite sitting on top of a native protobuf bridge. Distinctive pieces of that surface include a typed RPC layer for participant-to-participant method calls built directly on the data channel, structured byte/text data streams with incremental readers, and end-to-end encryption management exposed through the same ergonomic wrapper — all with minimal boilerplate to get a room connection publishing or subscribing to media.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search