rustrtc
A high-performance, full-stack real-time communication library — WebRTC, RTP/SRTP, T.38 Fax, and UPnP NAT traversal — all through a unified PeerConnection API.
Features
- High performance — ~3.4× faster than
webrtc-rsand ~3.2× faster thanpion(Go) in throughput, with ~47% less memory thanwebrtc-rs(see the benchmark below). - Full protocol stack — WebRTC, RTP, SRTP, and T.38 fax in a single library, plus UPnP IGD NAT traversal. Few moving parts, no missing pieces.
- Unified
PeerConnectionAPI — one interface for every transport mode (WebRtcICE/DTLS/SRTP,Srtp,Rtp, and T.38). No fragmented APIs. - WebRTC compliant — interoperable with Chrome/WebRTC and pion; offer/answer, renegotiation, rollback, and standard SDP attributes.
- ICE restart —
restart_ice()for network migration / re-INVITE flows, with automatic detection of remote-initiated restarts (RFC 8445 §9). - Complete media pipeline — packetizer/depacketizer (VP8, VP9, H264, Opus, G.711/G.722/G.729), jitter buffer, NACK/RTX, FIR/PLI, TWCC, and REMB for audio and video.
- Bandwidth estimation (GCC) — generates TWCC receiver feedback, stamps transport-wide sequence numbers on outbound RTP, and exposes a live
target_bitrateestimate for encoder adaptation (RtpSender::subscribe_target_bitrate). - Full ICE — STUN, TURN (UDP + TCP), ICE Lite, ICE TCP (RFC 6544), single-port UDP mux for SFU/WHEP deployments, and mDNS candidate obfuscation (
enable_mdns). - NAT traversal & deployment — RTP latching, UPnP IGD port mapping, and firewall-friendly port ranges (
rtp_start_port/rtp_end_port). - Production extras — RTP rewrite bridge (SSRC/PT/sequence remapping) and a WebRTC-compatible stats model.
Benchmark (rustrtc vs webrtc-rs & pion)
Fresh 3-way comparison (cargo run -r --example benchmark builds the webrtc-rs
and pion harnesses automatically):
| Metric | webrtc | rustrtc | pion | rustrtc advantage |
|---|---|---|---|---|
| Throughput (MB/s) | 159.81 | 550.40 | 171.39 | 3.4× webrtc / 3.2× pion |
| Msg Rate (msg/s) | 163,643 | 563,611 | 175,505 | 3.4× / 3.2× |
| Setup Latency (ms) | 3.09 | 0.57 | 1.20 | 5.4× / 2.1× faster |
| CPU Usage (%) | 674 | 736 | 671 | comparable (drives 3.4× the throughput) |
| Memory (MB) | 40 | 21 | 54 | -47% webrtc / -61% pion |
Key findings:
- Throughput:
rustrtcis ~3.4× faster thanwebrtc-rsand ~3.2× faster thanpion, with no regression after adding ICE restart, mDNS, VP9, and the TWCC/GCC pipeline. - Memory:
rustrtcuses ~47% less memory thanwebrtc-rsand ~61% less thanpion. - Setup latency: 0.57 ms vs 3.09 ms (webrtc-rs) / 1.20 ms (pion).
Reproduce with cargo run -r --example benchmark (numbers above from an 8-core
x86-64 Linux box, rustc 1.97 / go1.24; absolute values scale with hardware —
the ratios are the stable signal).
Usage
Here is a simple example of how to create a PeerConnection and handle an offer:
use ;
async
Configuration
All configuration goes through RtcConfiguration (or its builder RtcConfigurationBuilder):
Transport & Network
transport_mode—TransportMode::WebRtc(default),TransportMode::Srtp, orTransportMode::Rtp.ice_servers— STUN/TURN server list.ice_transport_policy—AllorRelay.rtp_start_port/rtp_end_port— Restrict RTP/ICE to a port range.external_ip— Override the external IP for ICE candidates (NAT scenarios).bind_ip— Bind to a specific local IP.disable_ipv6— Disable IPv6 candidate gathering.enable_ice_lite— Enable ICE Lite mode.ice_tcp_policy—IceTcpPolicy::Disabled(default),IceTcpPolicy::Enabled, orIceTcpPolicy::PassiveOnly. Controls ICE TCP candidate support per RFC 6544.ice_udp_mux/ice_udp_mux_port— Share a single UDP socket across manyPeerConnections (single-port multiplexing for SFU/WHEP). Setice_udp_mux = trueandice_udp_mux_port = <port>; incoming packets are demuxed by the server ufrag in the STUN Binding Request, then by remote source address.enable_mdns— Advertise host candidates via mDNS (<random>.localhostnames instead of local IPs, draft-ietf-rtcweb-mdns). A built-in mDNS responder answers A/AAAA lookups; real addresses are kept internally so connectivity is unaffected. Default:false.
Bandwidth Estimation (GCC)
enable_gcc— TWCC + GCC loop (default:true): outbound RTP is stamped with transport-cc sequence numbers, TWCC feedback is generated for inbound streams, and eachRtpSenderpublishes a bandwidth estimate. The library does not throttle sends itself — drive your encoder fromRtpSender::subscribe_target_bitrate():
let mut rx = sender.subscribe_target_bitrate.unwrap;
while let Ok = rx.changed.await
ICE Restart
pc.restart_ice.await?; // rolls fresh ICE credentials (RFC 8445 §9)
let offer = pc.create_offer.await?; // carries the new ice-ufrag/pwd
Remote-initiated restarts (peer offers new credentials) are detected and mirrored automatically. DTLS/SRTP survive across the restart.
UPnP
enable_upnp— Auto-map ports via UPnP IGD.upnp_lease_duration— UPnP port mapping lease duration in seconds (default: 3600).
RTP Latching
enable_latching— Enable dynamic remote address detection for RTP-only mode.probation_max_packets— Number of packets to observe before committing a latched address.
Media Capabilities
media_capabilities— Configure audio/video/image (T.38) codecs and SCTP port viaMediaCapabilities. Video presets:VideoCapability::default()(VP8),VideoCapability::vp9()/vp9_with_rtx(pt)(RFC 9628),VideoCapability::h264().ssrc_start— Starting SSRC value for local tracks.depacketizer_strategy— Pluggable per-kind depacketizer (e.g.Vp9Depacketizerfor RFC 9628 VP9 reassembly).
SCTP (Data Channels)
sctp_rto_initial,sctp_rto_min,sctp_rto_max,sctp_max_association_retransmits,sctp_receive_window,sctp_heartbeat_interval,sctp_max_heartbeat_failures,sctp_max_burst,sctp_max_cwnd
RTP Buffer
rtp_buffer_capacity— Per-SSRC receive buffer capacity.buffer_drop_strategy—DropNeworDropOldestwhen buffer is full.
use ;
// Using builder
let config = new
.transport_mode
.enable_latching
.probation_max_packets
.rtp_port_range
.enable_upnp
.ice_tcp_policy
.ice_server
.build;
let pc = new;
// Direct field access
let mut config = default;
config.transport_mode = WebRtc;
config.enable_latching = true;
config.rtp_start_port = Some;
config.rtp_end_port = Some;
config.enable_upnp = true;
T.38 fax
The t38 feature provides a complete T.38 v3 terminal: IFP wire codec, UDPTL
transport (with redundancy and gap recovery), a T.30 session engine
(CED/DIS → DCS/TCF → CFR → page → EOP/MCF → DCN, with timers and retries),
and V.21/V.27ter DSP for audio-gateway use.
use ;
use ;
let mut session = new;
session.role = Callee;
let endpoint = from_socket;
endpoint.set_codec;
let events = endpoint.run_call.await; // drives the whole fax session
spandsp interop e2e
tests/t38_spandsp_interop.rs runs real fax sessions against a spandsp-based
T.38 terminal (tools/t38-peer/t38_peer.py, ctypes over the system
libspandsp). Both directions are covered: rustrtc-caller→spandsp-callee
(pixel-exact page verification) and spandsp-caller→rustrtc-callee.
# requires: python3 + PIL, and libspandsp (brew install spandsp)
cargo test --features t38,t38-interop --test t38_spandsp_interop
Without the t38-interop feature the tests compile to nothing; with the
feature but without python3/libspandsp they skip at runtime.
Examples
You can run the examples provided in the repository.
SFU (Selective Forwarding Unit)
A multi-user video conferencing server. It receives media from each participant and forwards it to others.
-
Run the server:
-
Open your browser and navigate to
http://127.0.0.1:8081. Open multiple tabs/windows to simulate multiple users.

Echo Server
The echo server example demonstrates how to accept a WebRTC connection, receive data on a data channel, and echo it back. It also supports video playback if an IVF file is provided.
-
Run the server:
-
Open your browser and navigate to
http://127.0.0.1:3000.
DataChannel Chat
A multi-user chat room using WebRTC DataChannels.
-
Run the server:
-
Open your browser and navigate to
http://127.0.0.1:3000. Open multiple tabs to chat between them.
Audio Saver
Records audio from the browser's microphone and saves it to a file (output.ulaw) on the server.
-
Run the server:
-
Open your browser and navigate to
http://127.0.0.1:3000. Click "Start" to begin recording.
RTP Play (FFmpeg)
Streams a video file (examples/static/output.ivf) via RTP to a UDP port, which can be played back using ffplay.
-
Run the server:
-
In a separate terminal, run
ffplay(requires ffmpeg installed):
License
This project is licensed under the MIT License.