v1.0.2 Stable · 2026-11-03

A from-scratch C++20 WebRTC engine.
12.55 MB. Four platforms. No fork.

NimRTC is an embeddable media engine that keeps the wire-level WebRTC interop you need (Chrome peers, for both media and DataChannel) and replaces the 150–250 MB monolith with a layered, plugin-adapted engine you can grep, swap, and ship on aarch64. Same source tree ships a P2P client and a relay gateway (relay profile skips L2 codecs; a from-scratch SFU module is not a deliverable per the §7 pre-1.0 decision window closure, BDFL 2026-10-19). DTLS, RTP, audio 3A, and codecs are all behind header-only plugin interfaces.

  • 12.55 MBstatic lib
    (vs libwebrtc 150–250 MB)
  • 4 platformsWindows · Linux x86_64 · macOS arm64 · Linux aarch64
  • ~30 K LOCof C++20, end-to-end
    (libwebrtc is ~5.5M)
  • 9 profilescall · transport · relay · agent · agent-gateway · agent-low-latency · relay-agent · teleop · live

See it run

Two in-process NimRTCEngines run a real SDP exchange, gather ICE host candidates, run STUN connectivity checks on 127.0.0.1, and reach the connected state. Same engine, same wire, no test mock, no signal server. This is the examples/loopback-p2p binary, captured below.

The recording above is a synthesized trace of loopback-p2p's stderr output, generated from examples/loopback-p2p/loopback-p2p.cpp's fprintf calls. To re-record a real terminal session with your own build, run tools/record_loopback_demo.sh (or .ps1 on Windows) — it captures an asciinema cast and copies it here.

Quick start

No build needed to evaluate: download the v1.0.2 prebuilt bundle (vendored third-party stack — wolfSSL / libsrtp3 / libjuice / msquic — with .sha256 + .asc + sbom.json). Linking NimRTC itself still needs a source build for now: the NIMRTC_INSTALL=ON rules that produce NimRTC's own headers, static lib and NimRTCConfig.cmake are landed on main and ship in the next release. Or build the loopback example locally in ~3 minutes on a 4-core x86_64. All third-party deps are git submodules, SHA-pinned in src/third_party/vendor.json.

  1. Clone (with submodules)
    git clone --recurse-submodules https://github.com/NimRTC/nimrtc.git
    cd nimrtc
  2. Configure + build
    cmake --preset debug.msvc       # or: debug · debug.macos · debug.aarch64
    cmake --build build --target loopback-p2p -j
  3. Run the smoke test
    ./build/examples/Debug/loopback-p2p      # or .exe on Windows
    Expected output: [A ice] connected and [B ice] connected within ~2–3 s, then exit code: A=1 B=1, returning 0.
  4. Run the test suite + Chrome interop e2e
    ctest --preset tests --output-on-failure
    python tools/run_e2e_acceptance.py    # Chrome ↔ NimRTC Case D

What's working · what's not (be honest)

Shipped in v1.0.2 (Stable)

  • Patch release (v1.0.2, 2026-11-03): fixes the WebTransport ALPN mismatch and the oversized Windows bundle, and ships the signing public key with the release. 4-platform bundles + SBOM + detached GPG signatures.
  • Chrome ↔ NimRTC DataChannel bidirectional interop (DC-1) over WebTransport / QUIC, PASS E1–E6.
  • 9-profile library (call / transport / relay / agent / agent-gateway / agent-low-latency / relay-agent / teleop / live) with strict JSON↔C++ round-trip tests.
  • Pre/post-3A PCM tap (race-free set_pre_process_tap / set_post_process_tap, int16 ASR variant).
  • PAL Slice 1–8 — plugin-capability resolution, zero runtime overhead, public API unchanged.
  • Pluggable DTLS backend (EngineConfig::dtls_name resolves to wolfSSL by default, GMSSL opt-in).
  • Vendored libs: wolfSSL · libsrtp · libopus · libjuice · msquic · WebRTC APM. SHA-pinned.

Deferred to v1.x (and why)

  • DataChannel over SCTP-over-DTLS. Chrome is moving DataChannel to WebTransport over QUIC; the usrsctp socket class is @deprecated and still compiles for opt-in callers, but is no longer auto-registered.
  • iOS / Android native. Roadmap, not a current-track item. No ETA yet.
  • Production-grade hardening. API frozen at v1.0.2 per ADR-015 (NIMRTC_API_VERSION = 10002); SemVer guarantees apply from v1.0.1 (first published stable).

On the roadmap (main, ahead of v1.0.2)

  • v1.1 — Quality + packaging + hardening. Reproducible transport-floor benchmarks with CI artifacts; NIMRTC_INSTALL=ON install rules so find_package(NimRTC) works from an installed tree; WebRTC APM prebuilt shipped alongside; ISctpSocket lifecycle, ICE last_recv_packet() demux, p99 strategy validator, non-standard video clock-rate negotiation, DTLS IPv6 set_peer(), NAT-rebinding rehandshake(); Goog-CC BWE, unified adaptive jitter buffer, RTCP feedback loop, engine-level video stats, GMSSL vendoring + SRTP backend seam.

Architecture, in 30 seconds

Four compile-time layers (L0–L3) sit on top of a Plugin Adaptation Layer (PAL). A profile — also chosen at build time — decides which layers are even linked into the binary. The relay profile literally omits L2 codecs from the link.

┌─────────────────────────────────────────────────────────────┐
│  PROFILE  —  compile-time selection                          │
│  call │ transport │ relay │ agent │ agent-gateway │          │
│  agent-low-latency │ relay-agent │ teleop │ live             │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                     ▼
┌──────────────┐      ┌──────────────┐      ┌──────────────┐
│ L3  Engine   │      │ L2  Codecs   │      │ L1  Wire /   │
│ NimRTCEngine │ ←──→ │ + 3A         │ ←──→ │ state        │
│              │      │ Opus / H.264 │      │ RTP / ICE /  │
│              │      │ VP8 / 3A    │      │ DTLS / SRTP  │
└──────────────┘      └──────────────┘      └──────────────┘
                              │
                              ▼
                    ┌──────────────────────┐
                    │  PAL  —  zero-       │
                    │  overhead resolver   │
                    └──────────────────────┘
                              │
                              ▼
        ITransport · IICETransport · IRTP · ISDP · IJB
        IAudio3A · ICodec · IVideoSource/Sink · IDataChannel

Every capability swap (wolfSSL ↔ GMSSL; in-tree 3A ↔ HW 3A; libjuice ↔ custom ICE) flows through one of these header-only interfaces. The public NimRTCEngine API does not change.

This page · and what comes next

This page is a placeholder. It hosts a recording of the in-process loopback-p2p example, not a runnable browser demo. A real NimRTC-in-your-browser experience (Chrome ↔ NimRTC audio + video, with getUserMedia on the browser side and the transport profile compiled to wasm32-unknown-unknown) has not landed yet and is a longer-term candidate — it is not on the v1.0–v1.1 roadmap, which covers quality, packaging, hardening, and the weak-network chain.

In the meantime, if you want to see NimRTC actually move audio and video across a real browser peer, the Chrome interop CI (tools/run_e2e_acceptance.py) is the closest thing we have to a public-facing demo.