Native Shell
Native Shell: AI-generated UI, native in your app, on every platform. Apps on iOS, Android, macOS, Windows and Linux, GPUI apps and web pages load signed, sandboxed TSX modules at run time and draw th
WebRTC Implementation for TypeScript (Node.js), includes ICE/DTLS/SCTP/RTP/SRTP/WEBM/MP4
Translation pending
Developer toolsTypeScript · JavaScriptGitHub @shinyoshiakiSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Build media servers, gateways, recorders, bots, test peers, and custom real-time pipelines with a browser-compatible WebRTC API backed by a TypeScript stack you can inspect and extend down to ICE, DTLS, SCTP, RTP/RTCP, SRTP/SRTCP, and DataChannel.
Documentation · API Reference · Examples · Interoperability · Roadmap
werift (WebRTC Implementation for TypeScript) is a WebRTC implementation for Node.js written in TypeScript.
Use the browser-compatible RTCPeerConnection API when you want to build quickly, then drop down into ICE, DTLS, SCTP, RTP/RTCP, SRTP/SRTCP, or individual packets when your server-side application needs more control than a browser abstraction provides.
RTCPeerConnection, tracks, transceivers, DataChannels, standard events, ICE configuration, and stats in Node.js.sipsorcery/webrtc-interop matrices.npm install werift
The published werift package currently declares Node.js 22 or newer in its package metadata.
The API follows the familiar browser WebRTC model:
import { RTCPeerConnection } from "werift";
const offerer = new RTCPeerConnection();
const answerer = new RTCPeerConnection();
answerer.ondatachannel = ({ channel }) => {
channel.onmessage = ({ data }) => {
console.log("answerer received:", data.toString());
channel.send("hello from answerer");
};
};
const channel = offerer.createDataChannel("chat");
channel.onopen = () => {
channel.send("hello from offerer");
};
channel.onmessage = ({ data }) => {
console.log("offerer received:", data.toString());
};
await offerer.setLocalDescription(await offerer.createOffer());
await answerer.setRemoteDescription(offerer.localDescription!);
await answerer.setLocalDescription(await answerer.createAnswer());
await offerer.setRemoteDescription(answerer.localDescription!);
Here the two peers exchange SDP directly. setLocalDescription() gathers candidates before resolving, so this compact example can exchange the resulting descriptions without a separate trickle-ICE signaling path. Real applications can also use onicecandidate / addIceCandidate() and move signaling to WebSocket, HTTP, SIP infrastructure, a queue, or another transport.
See examples/datachannel for runnable variants.
werift exposes a browser-compatible WebRTC API for normal application code, including PeerConnection negotiation, tracks/transceivers, DataChannels, standard events, ICE configuration, and getStats().
A small number of intentional or known edge-case differences remain for backward compatibility or unsupported legacy APIs. They are documented separately in Browser API compatibility, together with the WPT strategy used to track exact browser behavior.
The core media APIs are packet-oriented: MediaStreamTrack can receive and emit RTP, so applications can connect WebRTC directly to an RTP router, recorder, transcoder, media pipeline, or test harness.
werift does not provide operating-system camera/microphone capture as part of the core PeerConnection API. Applications that need browser-style globals and register-backed navigator.mediaDevices.getUserMedia() can opt into werift/polyfill. The guide covers installation, cleanup, media registers, constraints, and TypeScript entrypoints.
flowchart LR
APP[Your TypeScript application]
PC[RTCPeerConnection]
SDP[SDP / negotiation]
ICE[ICE transport]
DTLS[DTLS]
SCTP[SCTP]
DC[DataChannel]
SRTP[SRTP / SRTCP]
RTP[RTP / RTCP]
MEDIA[Recorder / SFU / gateway / custom media pipeline]
APP <--> PC
PC --> SDP
PC --> ICE
ICE <--> DTLS
DTLS <--> SCTP <--> DC
ICE <--> SRTP <--> RTP <--> MEDIA
DTLS -. DTLS-SRTP keying .-> SRTP
DTLS and SRTP share the ICE transport, but media is not tunneled through DTLS: DTLS negotiates/exports keys for SRTP, while encrypted RTP/RTCP packets flow over the selected ICE path.
| Area | Highlights |
|---|---|
| Browser API | RTCPeerConnection, tracks/transceivers, DataChannel, standard events, ICE configuration, and browser-compatible negotiation behavior |
| ICE | Full ICE, local ICE-Lite mode, remote ICE-Lite interoperability, trickle ICE, ICE restart, ICE-TCP host candidates |
| STUN / TURN | STUN plus TURN relay control transports over UDP, TCP, and TLS; turn: / turns: URL handling |
| Security | DTLS-SRTP, SRTP, SRTCP, certificate/fingerprint handling |
| DataChannel | SCTP over DTLS, ordered/unordered delivery and partial-reliability controls |
| RTP / RTCP | RFC 3550, SR/RR, PLI, Generic NACK, REMB, Transport-Wide CC |
| Media resilience | RTX and RED (RFC 2198) |
| RTP payloads | RTP helpers for VP8, VP9, H.264, AV1, Opus, and RED-related workflows |
| Simulcast | Receive-side simulcast |
| Bandwidth estimation | Sender-side estimator driven by Transport-Wide CC feedback |
| Statistics | Browser-compatible getStats() report model for RTP, transport, ICE, codec, certificate, DataChannel, and related stats |
| Recording | Nonstandard MediaRecorder / WebM writer paths for Opus, VP8, VP9, H.264, and AV1 tracks; Ogg Opus (.ogg / .opus, or format: "ogg" for stream) for a single Opus audio track |
| Nonstandard media | MP4/WebM file playback via mediabunny plus configurable/dummy media-device sources |
| RTP processing | Jitter buffer, RED encoder/decoder, DTX, NACK, lip sync, and other packet processors |
werift's core strength is WebRTC transport, negotiation, and media-packet control. Device capture, rendering, and general-purpose transcoding remain application concerns; optional nonstandard helpers cover selected server-side media sources and sinks.
Receive encoded RTP, inspect or transform it, then forward it to other peers without forcing your application through a browser-style media pipeline.
A separate SFU project built with werift is available at node-sfu.
Record incoming WebRTC media or connect RTP to your existing storage/transcoding pipeline. See examples/save_to_disk and the nonstandard recorder APIs.
Use WebRTC as one side of a larger system: SIP/media gateways, device bridges, real-time backends, relay services, or application-specific transports.
Because the stack runs in Node.js and exposes packet/protocol state, it is useful for integration tests, interoperability suites, synthetic peers, load tests, and protocol debugging.
Use lower layers directly when you need custom ICE, DTLS, SCTP, RTP/RTCP, congestion-control, or packet-processing behavior.
Use the PeerConnection stack or only the protocol layer you need.
| Package | Purpose |
|---|---|
werift | Browser-compatible WebRTC API, media transport, DataChannel, and related APIs |
werift-ice | ICE / STUN / TURN client-side transport implementation |
werift-dtls | DTLS implementation |
werift-sctp | SCTP implementation |
werift-rtp | RTP / RTCP / SRTP / SRTCP and RTP processing utilities |
werift-ice-server | RFC 8489 STUN / RFC 8656 TURN server stack and Node reference implementation |
The top-level werift package also exports lower-level WebRTC transport and RTP primitives, so applications can mix the browser-compatible API with packet-level control.
Interoperability is validated at more than one level.
The repository contains browser E2E tooling and Chromium-focused coverage, including scenarios for ICE-Lite, ICE-TCP, and TURN relay over UDP/TCP/TLS. A Firefox test runner is also included in the E2E workspace.
Safari interoperability is community-verified. Community users have reported using werift extensively with Safari; see Issue #346. Safari is not currently part of the repository's automated browser E2E matrix, so this is presented as community validation rather than a CI guarantee.
werift is a participating implementation in sipsorcery/webrtc-interop, which maintains automated Peer Connection and Data Channel Echo tests. Its matrix includes werift alongside implementations such as:
This provides an independent interoperability signal in addition to werift's own E2E tests.
The examples directory contains runnable examples for high-level WebRTC use cases and lower-level media/protocol work.
| Example | What it demonstrates |
|---|---|
examples/datachannel | DataChannel offer/answer and messaging |
examples/mediachannel | Sending and receiving WebRTC media (installPolyfill + getUserMedia for RTP ingest) |
examples/save_to_disk | Recording encoded WebRTC media |
examples/turn-loopback | HTTPS + TURN/TLS multiplexed loopback and Chromium E2E |
examples/interop | Local interoperability peers (installPolyfill for RTP ingest) |
examples/untested/getStats | getStats() example code |
examples/untested | Root examples intentionally excluded from the examples E2E catalog |
packages/rtp/src/extra/processor | Jitter buffering, RED, DTX, NACK, lip sync, and RTP processing utilities |
npm run media
Then open:
https://shinyoshiaki.github.io/werift-webrtc/examples/mediachannel/pubsub/answer
Use the browser console and chrome://webrtc-internals/ to inspect the connection.
npm run datachannel
Then open:
https://shinyoshiaki.github.io/werift-webrtc/examples/datachannel/answer
Again, the browser console and chrome://webrtc-internals/ are useful for inspecting signaling, ICE, DTLS, SCTP, and DataChannel behavior.
werift provides a debug-compatible logger throughout the stack.
DEBUG=werift* node your-app.js
Applications can also switch logging at runtime through werift's exported API:
import { debug } from "werift";
debug.enable("werift*");
debug.disable();
The application's own debug package instance does not control werift logging. The logger supports the DEBUG patterns and common API shown above, but does not implement DEBUG_HIDE_DATE, DEBUG_DEPTH, DEBUG_SHOW_HIDDEN, logger.extend(), logger.log, debug.log, debug.formatters, logger.destroy(), logger.color, useColors, or inspectOpts. In browsers (for example werift-rtp bundled with Vite), set localStorage.debug before loading werift.
For browser interoperability debugging, combine server logs with:
chrome://webrtc-internals/Because the implementation is TypeScript, protocol behavior can be traced directly from application-level events into the relevant transport and packet-processing code.
Documentation coverage is still evolving. The examples and source remain useful references for developers working at protocol level.
If you are contributing to werift itself, initialize the pinned upstream Web Platform Tests submodule before running the WPT compatibility tooling:
git submodule update --init --recursive
The repository-level and core protocol package metadata declare Node.js 22 or newer. GitHub Actions validates Node.js 24, which is also required by the opt-in memory-leak harness.
The core WebRTC transport, browser-compatible API, and media-packet stack are implemented. Current work towards 1.0 focuses on hardening, test coverage, and developer experience:
turns:)werift has benefited from the wider WebRTC implementation ecosystem, including:
MIT
getStats() model