Repository navigation
Releases: MarshalX/python-webrtc
Release list
v0.1.0
🧪 The first beta: the API follows the specifications and is ready to build on, while compatibility between versions isn't guaranteed until 1.0.0
⚡ Data channels move 1.2–2.1 Gbps, 7.7–14.6x aiortc's throughput at 10–15% of its CPU per MB. See the benchmarks
🚀 A data channel opens 3.5 ms after createOffer, 7–8x faster than aiortc, and getStats takes 1.7 instead of 4.2 ms
🎥 Simulcast for every encoder, and H.264 on macOS that recovers from encoder faults and falls back to OpenH264
🧭 Transceiver, ICE, SCTP and track state change with the events that report them, as in browsers
🧩 Examples of a server for a browser page, a Gemini Live voice agent, and WHIP/WHEP streams
- Add simulcast for every encoder, on Windows too: each layer is sent in the negotiated codec at its scaled size, whether or not the encoder does simulcast itself. VP9 and AV1 need a
scalabilityModesuch asL1T1for each layer by @MarshalX in #254 - Fall back to OpenH264, once
await webrtc.openh264.install()has run, when VideoToolbox can't encode or decode by @MarshalX in #254 - Show transceiver, ICE, SCTP and track state with the events that change them:
mid,currentDirectionand the selected candidate pair change when their event fires, not before by @MarshalX in #259 - Add a Python server for a browser page example: your camera comes back in grayscale, and Python answers a chat over a data channel by @MarshalX in #268
- Add a Gemini Live voice agent example, with the API key kept on the server by @MarshalX in #268
- Add a WHIP/WHEP example that plays a live stream in the terminal or publishes one by @MarshalX in #268
- Add llms.txt, Markdown versions of the docs pages and Context7 and DeepWiki configs by @MarshalX in #265
- Credit node-webrtc in the third-party licences by @MarshalX in #262
- Speed up connection setup: keep libsrtp initialized and the network list updated, start the network manager and create port allocators without waiting on the network thread by @MarshalX in #261
- Speed up the first connection by running libsrtp's self-tests on their own thread by @MarshalX in #261
- Gather a candidate pool without waits between phases, and add ICE candidates in one signaling task by @MarshalX in #261
- Cut thread hops from negotiation and
getStats, and share concurrentgetStatscalls: 20 of them take 5.7 instead of 80.9 ms, renegotiation 22% less time and warm setup with trickle 18% less by @MarshalX in #255 - Cut signaling-thread waits from getters:
transceiver.midtakes 1.0 instead of 9.8 µs,sender.track38% less time,getSelectedCandidatePair()46% less and renegotiation 15% less by @MarshalX in #259 - Speed up data channels on macOS and Linux with a second, connected socket for a busy peer. Set the
PythonWebRTC-ConnectedSocketsfield trial toDisabledto turn it off by @MarshalX in #261 - Speed up data channel sends with one network-thread task per send, and skip the local address lookup on every UDP packet by @MarshalX in #261
- Convert received data channel messages once and deliver them with less Python per message by @MarshalX in #261
- Copy data channel messages once: 10–11% more throughput and 7–11% less CPU per MB for 1 KB messages by @MarshalX in #252
- Speed up event delivery, skip wake-ups while the event loop drains, and cache session descriptions between the events that change them by @MarshalX in #261
- Drop the unused audio processing and video render smoothing, which cost CPU on every received stream by @MarshalX in #249
- Send VP8 and H.264 at 720p with 6–9% less CPU per frame by @MarshalX in #256
- Wrap NV12 frames without copies, pass NV12 to VideoToolbox as it is, and pool frame buffers by @MarshalX in #257
- Copy video frame data once into pooled buffers, and convert VideoToolbox output to I420 in one pass by @MarshalX in #261
- Copy encoded frames less and cache RTP sources: 14% less CPU per transformed frame,
getSynchronizationSources()in 1.3 instead of 14.8 µs. A transform now queues up to 60 unread frames instead of 120 by @MarshalX in #258 - Fix sockets raising SIGPIPE on macOS, which kills the process where its default handler is restored by @MarshalX in #267
- Fix data channel stalls under load: UDP sockets get a receive buffer of at least 8 MB, which
WebRTC-SetSocketReceiveBufferoverrides. On Linux, raisenet.core.rmem_maxto allow it. See Field trials by @MarshalX in #261 - Fix a VideoToolbox frame that fails after the encoder took it: the session restarts with a key frame by @MarshalX in #254
- Fix a connection kept alive after
close()by the event loop it was bound to while closing by @MarshalX in #261 - Fix the operations of a closed event loop keeping their connections alive by @MarshalX in #261
- Fix the next operation starting before the code awaiting the previous one resumes, as in browsers by @MarshalX in #259
- Fix
addIceCandidatewithout a remote description rejecting late; it now rejects at once by @MarshalX in #261 - Fix sends that fail as the remote end closes: they fire
errorwithdata-channel-failure, and their bytes stay inbufferedAmountby @MarshalX in #252 - Fix remote data channels collected before their
openevent by @MarshalX in #259 - Fix DTMF tones and gaps raised to longer minimums than the specification's by @MarshalX in #253
- Fix standalone ICE gathering waiting 1 s between phases and gathering passive TCP candidates, and gather IPv6 where the host has it by @MarshalX in #253
- Fix the end of candidates of an earlier remote description shown after an ICE restart by @MarshalX in #253
- Fix the audio capture time, so the jitter doesn't jump after a send pause by @MarshalX in #253
- Fix
VideoTrackGeneratorframes written back to back dropped as duplicates by @MarshalX in #256 - Fix relayed remote video not scaled down for its encoder at low bitrates, and a sent track's own sinks getting the encoder's smaller frames by @MarshalX in #256
- Fix encoded frames a transform drops staying in memory while the event loop is busy or closed by @MarshalX in #260
- Fix writes to a writable stream slowing down as its queue grows by @MarshalX in #264
- Fix the empty reason in the OpenAI example's connection error by @MarshalX in #264
- Fix the OpenAI example printing the API key in
--helpby [@MarshalX](https://github.co...
v0.0.2
🔄 Coming from aiortc? Install wrtc[aiortc], change from aiortc to from webrtc.aiortc, and your code runs on Chrome's engine. See the migration guide
⚡ Data channels 14x faster (57 to 812 Mbps), 47x over 10 connections, with 88% less CPU per MB
🪶 80% less memory per audio connection, 27% less per data channel connection, 1450 connections instead of 200
📊 Benchmarks against aiortc, Pion, libdatachannel and webrtc-rs: against aiortc, connections open 5–7x faster, a data channel moves 4.5–9x more data, and audio costs less CPU
🧪 Test coverage up to 93.4% for C++ and 99.0% for Python, with the bugs it found fixed
- Add an aiortc compatibility layer with a migration guide by @MarshalX in #245
- Add benchmarks against four WebRTC libraries, with results and charts by @MarshalX in #242
- Add a benchmarks page to the docs, linked from the README and the docs home by @MarshalX in #243
- Speed up data channels: callbacks run on the network thread, every queued UDP datagram is read on a read event by @MarshalX in #243
- Wake event loops through the mailbox's eventfd or pipe instead of the Dispatcher thread: a native event reaches Python in 45 instead of 84 µs (p50), the Dispatcher stays for Windows by @MarshalX in #243
- Wait with kqueue on macOS by @MarshalX in #243
- Skip empty gathering phases: setup without trickle takes 5 instead of 125 ms by @MarshalX in #243
- Drop the RTC event log, share one receive buffer per thread, stop listening on TCP and regathering by @MarshalX in #243
- Cut audio CPU per stream by 41–47% by @MarshalX in #243
- Play Janus streams without an audio output, as on servers by @MarshalX in #239
- Fix
balancedandmaintain-frameratenever lowering the resolution by @MarshalX in #243 - Fix active TCP candidates rejected as a bad port by @MarshalX in #243
- Fix data channel messages arriving before the channel is announced, and a channel released before its last message is sent by @MarshalX in #243
- Fix sends from the
datachannelhandler lost before the channel opens by @MarshalX in #247 - Fix SFrame video recovery, and H.264 and AV1 with raw packetization by @MarshalX in #240
- Fix descriptions lost and
iceGatheringStatereadingcompleteafterclose()by @MarshalX in #240 - Fix key frame requests of a removed script transform never settling by @MarshalX in #240
- Fix the received
captureTimecounted from the NTP epoch by @MarshalX in #240 - Fix rollback allowed in the pranswer states by @MarshalX in #240
- Fix a
ValueErrorinset_parametersfor a codec without a MIME type by @MarshalX in #240 - Fix
maxMessageSizeof a dropped or closed SCTP transport by @MarshalX in #240 - Fix remote video sent on to another connection, and a local description missing the candidates gathered after the remote one was read by @MarshalX in #245
- Fix a loop closed while its drain was scheduled never being released by @MarshalX in #241
- Fix a closing connection and its channels being active but unbound, and loop release by @MarshalX in #244
- Fix a watched loop's state never released after the loop closes by @MarshalX in #247
- Fix an abort when a task queue is deleted from its own task by @MarshalX in #247
- Fix flaky waits in tests on free-threaded builds and slow cores by @MarshalX in #241
- Run tests in parallel and fix the test races it exposes by @MarshalX in #247
v0.0.1
🔌 The whole WebRTC API is bound. Every interface, every method, every dictionary: all 154 binding issues of the tracker are done, and the API goes beyond them
🎞 Media processing that not every browser ships yet: MediaStreamTrackProcessor, VideoTrackGenerator and MediaStreamTrackGenerator, with the VideoFrame and AudioData of WebCodecs
🔐 WebRTC Encoded Transform: the encoded frames of senders and receivers in Python with RTCRtpScriptTransform, and end-to-end encryption with SFrame
🎥 H.264 without bundling it: VideoToolbox on macOS, offered by default, and Cisco's OpenH264 binary on request elsewhere
🚀 Field trials and WARP: DTLS 1.3, SNAP and SPED cut round trips off connection setup
⚡ libwebrtc M152, pre-built wheels for Linux (x86_64 and aarch64), macOS and Windows, CPython 3.9 – 3.15, free-threaded 3.14t and 3.15t too
🧪 The public API follows the WebIDL of the specifications and runs the original web-platform-tests
📚 Fully reworked docs website: a new theme, guides, examples and the full API reference
What is bound, by specification:
- WebRTC:
RTCPeerConnection,RTCDataChannel,RTCRtpTransceiver,RTCRtpSender,RTCRtpReceiver,RTCDtlsTransport,RTCIceTransport,RTCSctpTransport,RTCDTMFSender,RTCCertificate,RTCIceCandidate,RTCSessionDescription, with every method, attribute, event and dictionary - WebRTC Extensions: standalone
RTCIceTransport, RTP header encryption, and more - WebRTC Statistics: 19 typed stats objects in
RTCStatsReport - WebRTC Encoded Transform:
RTCRtpScriptTransform,RTCEncodedVideoFrame,RTCEncodedAudioFrame, and SFrame (RFC 9605) - Media Capture and Streams:
MediaStream,MediaStreamTrackwith constraints, settings and capabilities, andMediaDeviceswith a synthetic camera and microphone - MediaStreamTrack Insertable Media Processing:
MediaStreamTrackProcessor,VideoTrackGenerator, andMediaStreamTrackGenerator - WebCodecs:
VideoFrameandAudioData - Streams:
ReadableStream,WritableStreamandTransformStream, with piping and async iteration
In numbers: 229 public classes, 50 enums with the string values of the specifications, 18 exceptions named after their DOMException, and the camelCase names of the specifications next to the snake_case ones.
- Migrate to prebuilt libwebrtc M152, scikit-build-core and single cibuildwheel CI by @MarshalX in #191
- Split wheel builds per Python version and cache libwebrtc by @MarshalX in #196
- Add Linux aarch64 wheels by @MarshalX in #207
- Support free-threaded Python with
cp314tandcp315twheels, add CPython 3.15 by @MarshalX in #232 - Implement WebRTC spec APIs and event ordering for WPT by @MarshalX in #195
- Add MediaStreamTrackProcessor, track generators and WebCodecs frames by @MarshalX in #197
- Align WebIDL dictionaries with the spec as typed models by @MarshalX in #212
- Align the public API with the WPT WebIDL by @MarshalX in #214
- Type event handlers per event, add listener management methods by @MarshalX in #215
- Add H.264 through Cisco's OpenH264 binary, downloaded on request by @MarshalX in #218
- Add H.264 on macOS through VideoToolbox, offered by default by @MarshalX in #219
- Encode H.264 with our own VideoToolbox session: AutoLevel, no rate freeze, High for Chrome by @MarshalX in #233
- Match browsers on SDP munging, connection states,
setParametersand close by @MarshalX in #227 - Replace
to_asyncwithcall_native, drop its timeout by @MarshalX in #206 - Add the OpenAI GPT-Live voice chat example by @MarshalX in #198
- Add field trials, connect the GPT-Live example with WARP, skip loopback candidates by @MarshalX in #225
- Add the Janus streaming example by @MarshalX in #205
- Play Janus streams in stereo by munging the Opus answer by @MarshalX in #234
- Rework the docs website with guides, examples and the API reference by @MarshalX in #217
- Rewrite the API docs with MDN links by @MarshalX in #221
- Run original web-platform-tests through a PythonMonkey shim by @MarshalX in #193
- Sync tests with web-platform-tests by @MarshalX in #192
- Compare the public API with the WPT WebIDL by @MarshalX in #211
- Add Atheris fuzz targets, fix findings by @MarshalX in #204
- Add strict clang-format and clang-tidy, fix all findings by @MarshalX in #203
- Enable all ruff rules, fix findings by @MarshalX in #210
- Type check with Pyrefly at full strictness, fix findings by @MarshalX in #213
- Run tests on GitHub Actions by @MarshalX in #187
- Build on Ubuntu 22.04 in CI by @MarshalX in #189
- Make CI wheel builds and PyPI publish safe to retry by @MarshalX in #226
- Retry and cache CI downloads, build the sdist in each wheel job by @MarshalX in #230
- Run isolated tests as functions instead of code strings by @MarshalX in #228
- Add an unattended bug hunt with stacks, crash triage and C++/Python coverage by @MarshalX in #231
- Update the licence holder and headers, rebuild third-party licences for M152 by @MarshalX in #220
- Fix wrapper ownership: shared_ptr lifetimes, no factory leaks or dangling observers by @MarshalX in #194
- Fix the GC deadlock by releasing wrappers off libwebrtc threads by @MarshalX in #199
- Fix deadlocks, leaks and crashes found by sanitizers and chaos tests by @MarshalX in #200
- Fix
set_parametershanging when libwebrtc drops the callback by @MarshalX in #208 - Fix sender and receiver leaks by releasing handlers of ended tracks by @MarshalX in #216
- Fix spec bugs found by a stricter WPT by @MarshalX in #222
- Fix callback crashes, exit hangs and thread churn in the native layer by @MarshalX in #223
- Fix stream, track and event-loop bugs, and a wrapper deadlock by @MarshalX in #224
- Release tasks stranded by a closed test loop by @MarshalX in #229
- Rebuild object lifetime: unreferenced connections, channels and live trac...