webrtc-rs/webrtc
Async-friendly WebRTC implementation in Rust
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5d ago
- ✓4 active contributors
- ✓Apache-2.0 licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 4 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 87% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/webrtc-rs/webrtc)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/webrtc-rs/webrtc on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: webrtc-rs/webrtc
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/webrtc-rs/webrtc shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 5d ago
- 4 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Small team — 4 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 87% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live webrtc-rs/webrtc
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/webrtc-rs/webrtc.
What it runs against: a local clone of webrtc-rs/webrtc — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in webrtc-rs/webrtc | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 35 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of webrtc-rs/webrtc. If you don't
# have one yet, run these first:
#
# git clone https://github.com/webrtc-rs/webrtc.git
# cd webrtc
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of webrtc-rs/webrtc and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "webrtc-rs/webrtc(\\.git)?\\b" \\
&& ok "origin remote is webrtc-rs/webrtc" \\
|| miss "origin remote is not webrtc-rs/webrtc (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/peer_connection/mod.rs" \\
&& ok "src/peer_connection/mod.rs" \\
|| miss "missing critical file: src/peer_connection/mod.rs"
test -f "src/runtime/mod.rs" \\
&& ok "src/runtime/mod.rs" \\
|| miss "missing critical file: src/runtime/mod.rs"
test -f "src/rtp_transceiver/mod.rs" \\
&& ok "src/rtp_transceiver/mod.rs" \\
|| miss "missing critical file: src/rtp_transceiver/mod.rs"
test -f "src/data_channel/mod.rs" \\
&& ok "src/data_channel/mod.rs" \\
|| miss "missing critical file: src/data_channel/mod.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 35 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~5d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/webrtc-rs/webrtc"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
webrtc-rs is a pure Rust implementation of the WebRTC API, designed as an async-first library that works with any async runtime (Tokio, async-std, smol, embassy). It provides a complete WebRTC stack (~95% W3C API coverage) by wrapping the sans-I/O rtc protocol core, enabling real-time peer-to-peer audio/video/data channel communication without requiring native bindings or external C libraries. Workspace monorepo: root webrtc crate wraps the sans-I/O rtc protocol core (located at rtc/rtc). Runtime adapters for Tokio (default), smol, and others are feature-gated. Examples live in examples/ directory with runnable demos (e.g., examples/data-channels-simple/data-channels-simple.rs, examples/broadcast/broadcast.rs). Dev tooling in .devcontainer/ and .github/workflows/ for consistent CI.
👥Who it's for
Rust developers building real-time communication applications (video conferencing, live streaming, P2P data transfer) who need a batteries-included WebRTC implementation that doesn't force a specific async runtime. Teams integrating WebRTC into Rust backends or embedded systems.
🌱Maturity & risk
Actively developed (v0.20.0-alpha.1 indicates pre-1.0 status). The project has CI/CD via GitHub Actions (cargo.yml, grcov.yml coverage), multiple working examples (broadcast, data-channels, play-from-disk, ice-restart), and dual MIT/Apache-2.0 licensing typical of mature Rust projects. It's past experimental but not yet production-grade — alpha versioning and numerous examples suggest the API is still stabilizing.
Standard open source risks apply.
Active areas of work
The project is transitioning toward a 'clean, ergonomic, runtime-agnostic implementation' as noted in the README. Edition 2024 (unusually recent for a Rust project) and alpha versioning suggest active refactoring. Multiple examples across data-channels, media playback (play-from-disk-h26x, play-from-disk-vpx), and ICE restart indicate ongoing feature parity work.
🚀Get running
git clone --recursive https://github.com/webrtc-rs/webrtc.git
cd webrtc
cargo build
cargo run --example data-channels-simple
Note: --recursive is needed because .gitmodules references submodules (the rtc workspace). Default feature runtime-tokio will be enabled.
Daily commands: Default Tokio runtime:
cargo run --example data-channels-simple
With smol runtime (if implementing that example):
cargo run --example <name> --no-default-features --features runtime-smol
Build and test:
cargo build
cargo test
🗺️Map of the codebase
src/lib.rs— Entry point exposing the public API and re-exports of all major modules (peer connection, data channels, media streams, transceivers).src/peer_connection/mod.rs— Core PeerConnection abstraction managing WebRTC signaling, ICE, and media negotiation state.src/runtime/mod.rs— Runtime abstraction layer enabling support for both Tokio and Smol async executors via feature flags.src/rtp_transceiver/mod.rs— RTP transceiver orchestration handling bidirectional media streams with sender/receiver responsibilities.src/data_channel/mod.rs— DataChannel implementation for reliable message delivery in WebRTC peer connections.Cargo.toml— Declares dual async runtime support (Tokio/Smol) and core dependencies including the internalrtccrate.src/peer_connection/driver.rs— Event loop and state machine driving peer connection lifecycle and async coordination.
🛠️How to make changes
Add support for a new audio codec
- Define codec constants and RTP payload type in a new module under src/media_stream/ (
src/media_stream/track_local/mod.rs) - Implement encoding logic in track_local to handle the new codec format (
src/media_stream/track_local/static_sample.rs) - Add corresponding decoder in remote track implementation (
src/media_stream/track_remote/static_rtp.rs) - Update transceiver offer/answer negotiation to advertise codec capability (
src/rtp_transceiver/mod.rs) - Write integration test validating codec selection with peer (
tests/codec_negotiation.rs)
Add a new example demonstrating a feature
- Create a new directory under examples/ with a descriptive name (
examples) - Create main.rs or example.rs file with async main using peer_connection API (
src/peer_connection/mod.rs) - Add README.md with setup instructions and feature explanation (
examples/README.md) - If HTML demo needed, reference existing pattern (e.g., demo.html) (
examples/data-channels-simple/demo.html)
Implement a new media track type
- Create new file in src/media_stream/track_local/ implementing Send trait (
src/media_stream/track_local/mod.rs) - Implement frame/sample encoding and RTP packetization (
src/media_stream/track_local/static_sample.rs) - Create corresponding receiver in track_remote/ (
src/media_stream/track_remote/mod.rs) - Integrate with transceiver to expose via add_track API (
src/rtp_transceiver/mod.rs) - Add example demonstrating the new track type (
examples)
Switch async runtime from Tokio to Smol
- In Cargo.toml, disable 'runtime-tokio' feature and enable 'runtime-smol' (
Cargo.toml) - Review runtime abstraction to confirm trait boundaries (
src/runtime/mod.rs) - Verify smol-specific spawn/block_on calls in runtime module (
src/runtime/smol.rs) - Test with smol-based example to confirm compatibility (
examples/data-channels-simple/data-channels-simple.rs)
🔧Why these technologies
- Rust + Async/Await — Memory safety without garbage collection; async traits enable efficient concurrent peer connections without thread-per-peer overhead.
- Tokio (default) + Smol (alternative) — Tokio for production (multi-threaded, battle-tested); Smol for embedded/minimal environments; abstraction via feature flags prevents lock-in.
- RTP/RTCP + SCTP — Industry-standard WebRTC protocols; RTP for media, SCTP for reliable ordered data channels.
- Internal 'rtc' crate dependency — Separates low-level protocol handling from high-level async API surface, enabling independent iteration.
- Dual MIT/Apache-2.0 license — Maximizes permissiveness and compatibility with both permissive and copyleft ecosystems.
⚖️Trade-offs already made
-
Async-only API (no blocking variants)
- Why: Aligns with Rust async ecosystem; forces elegant composition.
- Consequence: Cannot be used from synchronous contexts without explicit tokio::block_on() or smol::block_on().
-
Single rtc crate dependency for protocol logic
- Why: Centralizes complexity; easier to audit and version.
- Consequence: Tight coupling to internal rtc crate; no pluggable protocol implementations.
-
Runtime abstraction via feature flags (not traits)
- Why: Compile-time certainty; no runtime overhead.
- Consequence: Cannot switch runtimes at runtime; must recompile.
-
Stateful PeerConnection with driver event loop
- Why: Mirrors browser WebRTC API; natural state machine.
- Consequence: More complex error handling; driver task must be polled for events to propagate.
🚫Non-goals (don't propose these)
- Does not provide signaling protocol (SDP exchange must be handled by application)
- Does not include browser-based JavaScript bindings (pure Rust only)
- Does not handle audio/video encoding (delegates to external codecs via RTP track abstraction)
🪤Traps & gotchas
Submodule requirement: .gitmodules references the rtc workspace, so git clone --recursive is mandatory or you'll get missing dependency errors. Edition 2024: Rust edition 2024 is very recent (stabilized Oct 2024); ensures you're using a recent nightly or current stable Rust. Feature coupling: Default feature runtime-tokio is always enabled unless explicitly disabled; examples may fail silently on other runtimes if not feature-gated correctly. Sans-I/O abstraction: Protocol logic is in the separate rtc crate, so debugging real I/O issues (socket errors, timeouts) requires jumping between two crates.
🏗️Architecture
💡Concepts to learn
- Sans-I/O architecture — The entire protocol logic (ICE, DTLS, RTP) lives in the separate rtc crate with no I/O calls, enabling async-runtime-agnostic design and testability without socket mocking; core design pattern of this project.
- ICE (Interactive Connectivity Establishment) — Handles NAT traversal and peer discovery in WebRTC; the ice-restart example demonstrates renegotiation, a complex but necessary feature for long-lived connections.
- DTLS (Datagram Transport Layer Security) — Provides encryption for all WebRTC media and data channels; protocol state machine must be managed carefully in async context, a key complexity in this implementation.
- SDP (Session Description Protocol) negotiation — Core mechanism for offer/answer exchange describing media capabilities and codecs; examples like data-channels-offer-answer and play-from-disk-renegotiation demonstrate complex SDP handling.
- Feature-gated async runtimes — Cargo features (runtime-tokio, runtime-smol) allow single codebase to work with multiple async runtimes; requires careful abstraction to avoid runtime-specific APIs leaking into public interface.
- RTP/RTCP payload handling — Real-time Protocol is the foundation for audio/video transmission; examples like insertable-streams and play-from-disk-* require correct codec-specific framing and timing.
- Data channel flow control (SCTP) — WebRTC data channels use SCTP for reliability and ordering; the data-channels-flow-control example shows backpressure handling, critical for not overwhelming peers.
🔗Related repos
webrtc-rs/rtc— The core sans-I/O protocol implementation that this wrapper depends on; all WebRTC protocol logic lives here.webrtc-rs/media— Companion crate for media encoding/decoding and RTP payload handling; used by examples like play-from-disk-h26x.pion/webrtc— The original Go WebRTC implementation that inspired this Rust rewrite; useful for understanding protocol decisions and API design.tokio-rs/tokio— Default async runtime for this project; understanding Tokio internals helps with debugging async issues and runtime selection.async-rs/async-std— Alternative async runtime with similar capabilities to Tokio; webrtc-rs claims compatibility but examples primarily use Tokio.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for async runtime abstraction layer
The repo supports multiple async runtimes (tokio and smol) via feature flags, but there are no dedicated integration tests validating that core WebRTC functionality works identically across both runtimes. This is critical for ensuring portability and preventing runtime-specific regressions. Tests should cover connection establishment, data channel operations, and ICE restart scenarios across both features.
- [ ] Create tests/runtime_tokio.rs and tests/runtime_smol.rs with shared test macros
- [ ] Add test matrix in .github/workflows/cargo.yml to run tests with both runtime-tokio and runtime-smol features
- [ ] Implement tests covering: PeerConnection creation, data channel send/receive, ICE candidate handling
- [ ] Verify tests pass with: cargo test --features runtime-tokio and cargo test --features runtime-smol
Document and test the internal rtc crate dependency model
The Cargo.toml shows the main webrtc crate depends on rtc = { path = 'rtc/rtc' } which is a workspace member, but there's no documentation explaining the architectural relationship between webrtc and rtc crates, or validation that the public API properly re-exports critical rtc types. This causes confusion for contributors and potential API stability issues.
- [ ] Create docs/ARCHITECTURE.md explaining the webrtc → rtc crate hierarchy and what each crate owns
- [ ] Add doc comments to lib.rs listing all major re-exports from the rtc crate with pub use statements
- [ ] Add a tests/api_stability.rs test that validates core rtc types are re-exported and accessible via the webrtc crate
- [ ] Reference the new architecture doc in README.md under a 'Project Structure' section
Create comprehensive examples testing matrix and validation script
The repo has 20+ examples but no automated validation that they compile and run. Examples are outdated/broken silently, and new contributors don't know which examples work. A validation script and CI job would catch regressions early and serve as end-to-end tests.
- [ ] Create scripts/validate_examples.sh that attempts to build each example from examples/*/
- [ ] Add a new GitHub Actions workflow .github/workflows/examples.yml that runs the validation script on each push
- [ ] Mark clearly in examples/README.md which examples require external services (e.g., signaling server) vs. standalone
- [ ] Add cargo check for each example: for dir in examples/*/; do cargo check -p webrtc --example $(basename $dir); done
🌿Good first issues
- Add comprehensive integration tests for ICE restart flow:
examples/ice-restart/ice-restart.rsexists but there are likely no unit tests validating ICE state machine transitions; create tests intests/ice_restart.rsvalidating offer/answer/ICE candidate exchange. - Document runtime selection and async compatibility: The README mentions 'any async runtime' but examples directory only shows Tokio; add a runnable example in
examples/demonstrating the same data-channel scenario withruntime-smolfeature to prove portability. - Fill gaps in RTP/RTCP codec coverage: Multiple examples exist for H.264/VP8/VP9 playback (play-from-disk-h26x, play-from-disk-vpx) but likely incomplete SDP negotiation for all codecs; audit and expand codec handling in rtc crate's SDP parsing.
⭐Top contributors
Click to expand
Top contributors
- @yngrtc — 87 commits
- @rainliu — 11 commits
- @zhao-gang — 1 commits
- [@Rusty Rain](https://github.com/Rusty Rain) — 1 commits
📝Recent commits
Click to expand
Recent commits
0fdc239— Update branches for workflow triggers (rainliu)2adda95— add simulcast_add_transceiver_from_kind.rs (rainliu)6fe8605— Negotiating codecs when sender supports multiple options #737 (rainliu)6c86339— fix simulcast with register_default_codecs issue (rainliu)db3e9bc— fix save to hevc (rainliu)11d3228— fix and verify H265 packetizer/depacketizer issue in simulcast example and play-from-disk-h26x/save-to-disk-h26x example (rainliu)9df59fe— Negotiating codecs when sender supports multiple options #737 (rainliu)cb26d2e— update RTC pointer (rainliu)20575a3— update example data-channels-flow-control (#783) (zhao-gang)b899593— bump version to "0.20.0-alpha.1" (yngrtc)
🔒Security observations
The webrtc-rs codebase shows a generally sound security posture as a Rust-based WebRTC implementation. However, there are several concerns: (1) Invalid Rust edition configuration that must be corrected, (2) reliance on local alpha-version dependencies that complicate stability and auditability, (3) lack of explicit cryptographic dependency declarations making security audits harder, and (4) absence of a security disclosure policy. The use of modern Rust (async/await, strong typing) provides inherent safety benefits. No obvious hardcoded secrets, injection vulnerabilities, or misconfigured ports were detected in the visible file structure. Recommendations focus on correcting the edition issue, implementing proper dependency management, establishing security practices, and running regular vulnerability scans via
- High · Invalid Rust Edition in Cargo.toml —
Cargo.toml. The Cargo.toml specifies edition = '2024', which is not a valid Rust edition. Valid editions are 2015, 2018, and 2021. This will cause compilation failures and indicates a potential misconfiguration that could lead to unexpected behavior or security implications if the actual edition differs from intent. Fix: Change 'edition = "2024"' to a valid edition such as 'edition = "2021"' (the latest stable edition). - Medium · Dependency on Local Path with Alpha Version —
Cargo.toml - rtc dependency. The crate depends on 'rtc' version '0.20.0-alpha.1' via a local path dependency. Alpha versions are unstable and may contain unvetted security issues. Additionally, using local path dependencies in published crates can cause dependency resolution issues for end users. Fix: Either publish the rtc crate to crates.io with a stable version, or if this is a workspace, document the workspace structure clearly. Avoid shipping alpha versions in production releases. - Medium · Missing Security-Related Dependencies Review —
Cargo.toml. The crate uses async runtime abstractions (tokio, smol) and cryptographic operations typical of WebRTC. However, there is no explicit dependency on cryptographic libraries (e.g., ring, rustls) in the visible Cargo.toml. These likely come transitively through the 'rtc' dependency, making security auditing more difficult. Fix: Explicitly declare or audit all cryptographic dependencies. Ensure transitive dependencies are reviewed using 'cargo tree' and 'cargo audit'. Run 'cargo audit' regularly in CI/CD to detect known vulnerabilities. - Medium · Incomplete File Structure in Cargo.toml —
Cargo.toml - examples section. The provided Cargo.toml shows incomplete [[example]] definitions (the 'data-channels-answer' example entry is cut off). This suggests the file may have been improperly parsed or modified, which could mask potential security issues or configuration errors. Fix: Ensure the Cargo.toml is complete and properly formatted. Validate with 'cargo check' and ensure all example definitions are properly closed. - Low · Development Dependencies Include HTTP Client (hyper) —
Cargo.toml - dev-dependencies. The dev-dependencies include hyper with 'full' features. While this is acceptable for examples and testing, it increases the attack surface for development/example code. If example code is not properly sandboxed or isolated, it could introduce vulnerabilities. Fix: Consider using a minimal feature set for hyper (e.g., removing 'full' and only enabling required features). Ensure example code follows secure coding practices and is not exposed in production builds. - Low · No Explicit Security Policy or SECURITY.md —
Repository root. The repository structure shows no visible SECURITY.md file for responsible disclosure policies. This makes it harder for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file documenting the vulnerability disclosure process and security contact information. - Low · Broad Async Runtime Feature Flags —
Cargo.toml - features section. The crate provides multiple async runtime options (tokio, smol) via feature flags. While flexible, this increases the complexity of the codebase and makes comprehensive security testing more challenging, as each runtime path may have different behavior. Fix: Ensure comprehensive testing for each runtime feature flag combination. Document any runtime-specific security considerations in the crate documentation.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.