+{%- endblock body_before %}
diff --git a/docs/source/benchmarks.md b/docs/source/benchmarks.md
index ab08947..81477c8 100644
--- a/docs/source/benchmarks.md
+++ b/docs/source/benchmarks.md
@@ -64,7 +64,7 @@ This chart favors aiortc, for two reasons that come from the engine rather than
controller and its transport. The Python objects on top take under 1 KB.
- **A connected data channel** is mostly ICE: the engine keeps every candidate pair it checked, about 8 KB each, to
switch networks without reconnecting. The benchmark Mac has 10 addresses (Wi-Fi, VPN, virtual machine bridges and
- loopback), each over UDP and TCP, so 50 pairs a connection. aiortc gathers UDP only and skips loopback. In the same
+ loopback), each over UDP and TCP, so 50 pairs a connection. aiortc gathers UDP only. In the same
test on Linux with one interface, a connected pair takes a third of the memory it takes on that Mac.
Memory stays reserved after connections close, because the allocator keeps it for reuse: opening and closing 100
@@ -87,8 +87,8 @@ close. H.264 is cheaper at every resolution, decoded by VideoToolbox on macOS.
Both libraries send under the same bitrate cap. Read the two panels under the bars before the bars:
-- **Bitrate over the cap.** Python WebRTC stays under the cap. aiortc's VP8 ignores it as the picture grows: twice the
- cap at 1080p60 and five times at 2160p. Sent to a real network, that is packet loss.
+- **Bitrate over the cap.** Python WebRTC stays under the cap. aiortc's VP8 ignores it as the picture grows: 2.4 times
+ the cap at 1080p60 and five times at 2160p. Sent to a real network, that is packet loss.
- **Frame rate over the source.** To fit 1080p and 4K into 1.5 Mbps, the engine keeps the resolution and drops
frames, as browsers do with that setting. It encodes fewer, much larger frames, so the CPU per frame goes up.
@@ -101,8 +101,9 @@ encoder on macOS and costs a tenth of the CPU per frame.
Two peers of the same library call each other, and each library's congestion control picks the bitrate. Python WebRTC
reaches the bitrate the video asks for, 2.5 or 5 Mbps, while aiortc stays near 1.5–2.4 Mbps. The panel under the bars
-shows it: Python WebRTC receives up to three times the bits for every frame, so a better picture, and decoding more
-bits costs more CPU per frame.
+shows it: Python WebRTC receives up to 2.8 times the bits for every frame, and decoding more bits costs more CPU per
+frame. That isn't the whole cost: at H.264 720p the bits per frame are within 6%, and Python WebRTC's receiver still
+takes more CPU per frame.

diff --git a/docs/source/conf.py b/docs/source/conf.py
index b80597b..60d5a26 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -132,6 +132,10 @@
html_css_files = [
'css/custom.css',
]
+html_js_files = [
+ ('js/copy-page.js', {'defer': 'defer'}),
+]
+templates_path = ['_templates']
html_theme_options = {
'show_prev_next': True,
@@ -206,6 +210,7 @@
# -- llms.txt ---------------------------------------------------
# a Markdown copy of every page, e.g. /quickstart.md, for agents
llms_txt_override_source = 'llms-txt'
+llms_txt_suffix_mode = 'url-suffix'
llms_txt_nested_enabled = False
llms_txt_full_build = True
LLMS_MARKDOWN_BUILDER = 'llms-markdown'
diff --git a/docs/source/guides/comparison.md b/docs/source/guides/comparison.md
new file mode 100644
index 0000000..9706b68
--- /dev/null
+++ b/docs/source/guides/comparison.md
@@ -0,0 +1,132 @@
+---
+description: "Which Python WebRTC library to use: Python WebRTC (wrtc), aiortc, the LiveKit SDK and GStreamer webrtcbin compared on engine, API, codecs, platforms and performance."
+---
+
+# Choosing a Python WebRTC library
+
+Four libraries bring WebRTC to Python: Python WebRTC (`wrtc` on PyPI), aiortc, LiveKit's Python SDK and GStreamer's
+webrtcbin. This page compares them as of 24 October 2026, with a source for every fact about the others in
+[Sources](#sources).
+
+## Which one, and when
+
+- **Python WebRTC**: you want libwebrtc, the WebRTC engine of Chrome, with the browser's API, peer-to-peer to any
+ WebRTC endpoint: browsers, SFUs, media servers, AI voice APIs. Prebuilt wheels for Linux, macOS and Windows,
+ free-threaded Python included.
+- **aiortc**: you need ORTC objects below the peer connection, such as a standalone `RTCIceTransport`, a protocol
+ stack written in Python that you can read and patch, less memory per connection than Python WebRTC, or a release line marked stable.
+ Python WebRTC is a pre-1.0 beta. aiortc's own examples run on Python WebRTC with only their imports changed: see
+ [Migrating from aiortc](aiortc.md).
+- **LiveKit SDK**: you build on LiveKit: its rooms, LiveKit Cloud or a self-hosted LiveKit server. It connects to a
+ LiveKit server only, not to other WebRTC endpoints.
+- **GStreamer webrtcbin**: your media already lives in GStreamer pipelines, such as capture devices, hardware
+ encoders, RTSP sources or mixing, and WebRTC is one more element in them.
+
+## Features
+
+| | **Python WebRTC** | aiortc | LiveKit SDK | GStreamer webrtcbin |
+|---------------------------|----------------------------|--------------------------|------------------------------|-----------------------|
+| Engine | libwebrtc M152 | own, in Python | libwebrtc M150, through Rust | own, in C |
+| Connects to | any WebRTC endpoint | any WebRTC endpoint | a LiveKit server | any WebRTC endpoint |
+| API | W3C, asyncio | close to W3C, asyncio | rooms and tracks, asyncio | GObject signals |
+| Media path | native | Python | native | native |
+| Video codecs | VP8, VP9, AV1, H.264 | VP8, H.264 | VP8, VP9, AV1, H.264, H.265 | installed plugins |
+| Audio codecs | Opus, G.722, G.711 | Opus, G.722, G.711 | Opus, G.711 | installed plugins |
+| Trickle ICE | ✅ | half | ✅ | ✅ |
+| Simulcast | ✅ sending | ❌ | ✅ | since 1.22 |
+| Encoded transforms | ✅ | ❌ | ❌ | — |
+| End-to-end encryption | ✅ SFrame | ❌ | ✅ AES-GCM | — |
+| Free-threaded Python | ✅ 3.14t, 3.15t | — | — | GIL turned back on |
+| Python | 3.9–3.15 | 3.10+ | 3.9+ | 3.10–3.14 |
+| Wheels | Linux, macOS, Windows | pure Python | Linux, macOS, Windows | macOS, Windows |
+| Tested with | browsers' web-platform-tests | own suite, browser interop | own suite | own unit tests |
+| Latest release | 0.1.0 beta, Oct 2026 | 1.15.0 stable, Jul 2026 | 1.1.21, Oct 2026 | 1.28.8, Oct 2026 |
+
+— means the documentation doesn't say.
+
+- **Media path.** Native means RTP, encoding and decoding run outside Python, and your code sees frames. aiortc runs
+ RTP, RTCP and its jitter buffer in Python, with DTLS by OpenSSL, SRTP by libsrtp and codecs by FFmpeg.
+- **H.264.** Python WebRTC uses VideoToolbox on macOS, and Cisco's OpenH264 elsewhere after one
+ `openh264.install()` call: it never bundles H.264. See [H.264](h264.md). aiortc encodes with x264 from PyAV's
+ wheels. LiveKit uses hardware encoders where it has them and a bundled OpenH264 otherwise.
+- **LiveKit.** H.265 needs a hardware encoder: VideoToolbox on macOS, NVENC on Linux x86_64. Opus and G.711 are the
+ server's default audio codecs.
+- **GStreamer.** Its Windows wheels for 3.13t and 3.14t ship PyGObject 3.50, which doesn't declare free-threading
+ support, so Python turns the GIL back on. It has no Linux wheels: Linux distributions package it.
+- **Tests.** Python WebRTC runs the browsers' web-platform-tests unmodified, through a binding shim in
+ [`tests/wpt`](https://github.com/MarshalX/python-webrtc/tree/main/tests/wpt), whose `expectations.json` lists what
+ doesn't pass.
+
+## Performance
+
+The [benchmarks](../benchmarks.md) compare Python WebRTC with aiortc on one Apple M1. Python WebRTC opens a data
+channel in 3.5 ms against 29.0 ms, moves 7.7–14.6x the data and spends 25–70% of aiortc's CPU on audio. aiortc uses
+less memory per connection and less CPU per frame sending VP8 and receiving video calls; the benchmarks page explains
+why. The LiveKit SDK and GStreamer aren't measured.
+
+## Sources
+
+The facts about the other libraries, as checked on 24 October 2026. Links to code point at the release compared.
+
+:::{dropdown} Show the sources
+
+**aiortc**
+
+- The [README](https://github.com/aiortc/aiortc): the Python implementation on asyncio, ORTC, half-trickle ICE, and
+ interop testing with Chrome and Firefox.
+- The [codec list](https://github.com/aiortc/aiortc/blob/1.15.0/src/aiortc/codecs/__init__.py), the
+ [H.264 codec](https://github.com/aiortc/aiortc/blob/1.15.0/src/aiortc/codecs/h264.py) on x264 and FFmpeg, and the
+ [changelog](https://aiortc.readthedocs.io/en/latest/changelog.html): G.722 since 1.13.0, PyAV for every codec since
+ 1.12.0.
+- The [API reference](https://aiortc.readthedocs.io/en/latest/api.html): the ORTC objects, and no send encodings,
+ simulcast or encoded transforms.
+- The [jitter buffer](https://github.com/aiortc/aiortc/blob/1.15.0/src/aiortc/jitterbuffer.py), and the
+ [pyproject.toml](https://github.com/aiortc/aiortc/blob/1.15.0/pyproject.toml) with its dependencies on PyAV,
+ pyOpenSSL and pylibsrtp.
+- [PyPI](https://pypi.org/project/aiortc/): version 1.15.0 of 13 July 2026, Python 3.10+, the Production/Stable
+ classifier and the single `py3-none-any` wheel.
+
+**LiveKit SDK**
+
+- The [README](https://github.com/livekit/python-sdks): rooms, the connection to LiveKit Cloud or a self-hosted
+ server, Python 3.9+, and the table of hardware codecs by platform.
+- The [Rust SDK](https://github.com/livekit/rust-sdks) it is built on, its
+ [`libwebrtc` crate](https://docs.rs/crate/libwebrtc/latest), "Livekit safe bindings to libwebrtc", and, at the
+ commit 1.1.21 builds on, the
+ [`.gclient`](https://github.com/livekit/rust-sdks/blob/5a656c4bc4bc5c4f7fad17ab69044db3b487dfeb/webrtc-sys/libwebrtc/.gclient)
+ that pins `m150_release` and the
+ [session](https://github.com/livekit/rust-sdks/blob/5a656c4bc4bc5c4f7fad17ab69044db3b487dfeb/livekit/src/rtc_engine/rtc_session.rs)
+ that trickles candidates over LiveKit's signalling.
+- The [`TrackPublishOptions` definition](https://github.com/livekit/rust-sdks/blob/main/livekit-ffi/protocol/room.proto)
+ and the [advanced media guide](https://docs.livekit.io/transport/media/advanced/): simulcast.
+- The server's [default codecs](https://github.com/livekit/livekit/blob/master/pkg/config/config.go): Opus and G.711.
+- The Python reference: its [modules](https://docs.livekit.io/reference/python/livekit/rtc/index.html), with no
+ encoded-frame transform (`encoded_video` publishes frames encoded elsewhere), and
+ [E2EE](https://docs.livekit.io/reference/python/livekit/rtc/e2ee.html), with AES-GCM. The
+ [encryption guide](https://docs.livekit.io/transport/encryption/start/).
+- The [tests workflow](https://github.com/livekit/python-sdks/blob/rtc-v1.1.21/.github/workflows/tests.yml).
+- [PyPI](https://pypi.org/project/livekit/): version 1.1.21 of 16 October 2026 and its wheels.
+
+**GStreamer webrtcbin**
+
+- The [element's documentation](https://gstreamer.freedesktop.org/documentation/webrtc/index.html): its package, its
+ signals (`create-offer`, `on-ice-candidate`, `add-ice-candidate` and others) and "implements the majority of the
+ W3's peerconnection API".
+- The [rtp plugin](https://gstreamer.freedesktop.org/documentation/rtp/index.html)'s payloaders, and the
+ [AV1](https://gstreamer.freedesktop.org/documentation/rsrtp/rtpav1pay.html) one.
+- The [1.22 release notes](https://gstreamer.freedesktop.org/releases/1.22/): "Initial support for sending or
+ receiving simulcast streams".
+- The [1.28 release notes](https://gstreamer.freedesktop.org/releases/1.28/): the wheels for macOS and Windows, and
+ 1.28.8 of 8 October 2026. The [Linux install guide](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html):
+ "included in all Linux distributions".
+- The [unit tests](https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/1.28.8/subprojects/gst-plugins-bad/tests/check/elements/webrtcbin.c)
+ of webrtcbin.
+- [PyPI](https://pypi.org/project/gstreamer-python/): `gstreamer-python` 1.28.8, its wheels for CPython 3.10–3.14 and
+ the free-threaded ones for Windows.
+- The [build recipe](https://gitlab.freedesktop.org/gstreamer/cerbero/-/blob/1.28/recipes/pygobject.recipe) of the
+ wheels' PyGObject 3.50.2, its [module](https://gitlab.gnome.org/GNOME/pygobject/-/blob/3.50.2/gi/gimodule.c), and
+ Python's [free-threading guide](https://docs.python.org/3/howto/free-threading-python.html): "The GIL may also
+ automatically be enabled when importing a C-API extension module that is not explicitly marked as supporting free
+ threading."
+
+:::
diff --git a/docs/source/guides/index.md b/docs/source/guides/index.md
index 11bed38..994eaa7 100644
--- a/docs/source/guides/index.md
+++ b/docs/source/guides/index.md
@@ -1,5 +1,5 @@
---
-description: "Guides to Python WebRTC: connections, data channels, media, events, H.264, field trials and migrating from aiortc."
+description: "Guides to Python WebRTC: connections, data channels, media, events, H.264, field trials, choosing a library and migrating from aiortc."
---
# Guides
@@ -52,6 +52,13 @@ Enabling H.264 with Cisco's OpenH264 binary, and its licensing.
Experimental features of the engine, and WARP for faster connections.
:::
+:::{grid-item-card} {octicon}`git-compare;1em;sd-mr-1` Choosing a library
+:link: comparison
+:link-type: doc
+
+Python WebRTC, aiortc, the LiveKit SDK and GStreamer webrtcbin compared, and when to use each.
+:::
+
:::{grid-item-card} {octicon}`arrow-switch;1em;sd-mr-1` Migrating from aiortc
:link: aiortc
:link-type: doc
diff --git a/docs/source/index.md b/docs/source/index.md
index cd3877d..3444525 100644
--- a/docs/source/index.md
+++ b/docs/source/index.md
@@ -105,10 +105,12 @@ Prebuilt wheels for Linux, macOS and Windows, including free-threaded Python. No
| Browser API (`RTCPeerConnection`, `createOffer`, …) | ✅ | similar | ❌ rooms | ❌ GObject signals |
| Media path | native | Python | native | native |
| VP9 and AV1 | ✅ | ❌ | ✅ | ✅ |
-| `pip install` on Linux, macOS and Windows | ✅ | ✅ | ✅ | ❌ system packages |
+| `pip install` on Linux, macOS and Windows | ✅ | ✅ | ✅ | ❌ no Linux wheels |
-Against aiortc, it opens connections 7–8x faster, moves 7.7–14.6x more data through a data channel and spends less
-CPU on audio. See the [benchmarks](benchmarks.md), which also measure Pion, libdatachannel and webrtc-rs.
+Against aiortc, it opens connections 7.3–8.3x faster, moves 7.7–14.6x more data through a data channel and spends
+less CPU on audio. See the [benchmarks](benchmarks.md), which also measure Pion, libdatachannel and webrtc-rs.
+
+The full comparison, and when another library is the better choice: [Choosing a Python WebRTC library](guides/comparison.md).
## Where to start
@@ -199,6 +201,7 @@ guides/events
guides/media
guides/h264
guides/field-trials
+guides/comparison
guides/aiortc
```
diff --git a/docs/source/llms-txt.md b/docs/source/llms-txt.md
index 2eaf5bb..670b07d 100644
--- a/docs/source/llms-txt.md
+++ b/docs/source/llms-txt.md
@@ -22,6 +22,8 @@ of date.
## Start
- {doc}`Quickstart `: installation, and two peers connected with a data channel.
+- {doc}`Choosing a Python WebRTC library `: Python WebRTC, aiortc, the LiveKit SDK and GStreamer
+ webrtcbin compared, and when each is the better choice.
- {doc}`Migrating from aiortc `: run aiortc code by changing its imports, and what changes on the way.
## Guides