aiortc
A pure-Python implementation of WebRTC and ORTC built on asyncio, for real-time audio, video, and data channel communication.
Repository Health
Technical Analysis
aiortc brings WebRTC and ORTC to Python by implementing the full protocol stack — ICE, DTLS, SRTP, SCTP, RTP/RTCP, and SDP negotiation — directly in Python on top of asyncio, rather than wrapping a native browser engine. Its public API mirrors the JavaScript WebRTC API closely while swapping promises for coroutines and using pyee’s EventEmitter for events, so developers already familiar with browser WebRTC can transfer that knowledge directly.
Because the implementation is readable Python rather than opaque native code, it doubles as both a production media/data-channel transport and a reference for understanding how WebRTC actually works under the hood. It interoperates with Chrome and Firefox, supports Opus/PCMU/PCMA audio and VP8/H.264 video via PyAV, and lets developers plug Python-ecosystem tooling — computer vision, custom signaling, server-side media pipelines — directly into the media path.
What You Get
- A W3C-API-shaped RTCPeerConnection for offer/answer SDP negotiation, ICE gathering/connectivity checks, and DTLS/SRTP-secured media
- Pure-Python SCTP implementation for WebRTC data channels, with no native SCTP dependency
- Audio and video codec support (Opus, PCMU, PCMA, VP8, H.264) via PyAV for encoding/decoding
- contrib.media helpers (MediaPlayer, MediaRecorder, MediaRelay) for reading/writing files and streams as WebRTC tracks
- contrib.signaling helpers plus ready-to-run examples (server, webcam, datachannel-cli, datachannel-filexfer, janus) covering common signaling patterns
- RTCStatsReport and related stats classes for inbound/outbound RTP and transport-level monitoring
Common Use Cases
- Building a Python signaling/media server that exchanges audio, video, or data with browser WebRTC clients
- Streaming a webcam, screen, or synthetic video source (e.g. from OpenCV) into a browser over WebRTC
- Peer-to-peer file transfer or low-latency messaging over WebRTC data channels between Python processes
- Bridging WebRTC to other Python real-time systems (e.g. Janus, custom SFUs) for gateway or recording use cases
- Prototyping or teaching WebRTC internals, since the protocol stack is plain, readable Python instead of native bindings
Under The Hood
Architecture aiortc mirrors the W3C WebRTC layering directly in its module structure: RTCPeerConnection (src/aiortc/rtcpeerconnection.py) orchestrates SDP offer/answer negotiation and owns the transport stack beneath it — RTCIceTransport for ICE gathering/connectivity (delegated to the separate aioice package), RTCDtlsTransport for the DTLS handshake and SRTP keying, and RTCSctpTransport, a from-scratch pure-Python SCTP implementation, for data channels. RTP/RTCP media flows through RTCRtpSender/RTCRtpReceiver/RTCRtpTransceiver, with codec-specific packetization handled by a small codecs package (base.py defining the encoder/decoder interface, with opus.py/vpx.py/h264.py/g711.py/g722.py as implementations). contrib/media.py sits above this as an integration layer using PyAV to bridge files and OS media devices into MediaStreamTrack objects. Changing the core RTCIceTransport/RTCDtlsTransport contract would ripple through every layer above it, since each transport is instantiated and composed directly inside RTCPeerConnection rather than behind a pluggable interface.
Tech Stack
The library targets Python 3.10–3.14 and is built on asyncio throughout, with pyee’s AsyncIOEventEmitter providing the browser-style event model (ontrack, ondatachannel, etc.). Core dependencies are narrowly scoped: aioice handles ICE candidate gathering/STUN, av (PyAV, an ffmpeg binding) handles audio/video encode-decode, cryptography and pyOpenSSL provide the DTLS handshake and certificate generation, pylibsrtp wraps libsrtp for SRTP encryption, and google-crc32c accelerates SCTP checksums. Packaging uses setuptools with a src/ layout and dynamic versioning from aiortc.__version__; there is no web framework dependency since the library is transport-only and leaves signaling to the application.
Code Quality The project has 24 test modules under tests/ using Python’s unittest.TestCase, exercising RTP/RTCP/SCTP wire parsing against real captured binary fixtures (rtp.bin, sctp_cookie_echo.bin, rtcp_sr.bin, etc.) alongside protocol-level tests of RTCPeerConnection negotiation and codec round-trips. CI (.github/workflows/tests.yml) runs the suite with coverage across Python 3.10 through 3.14, and a separate lint job runs ruff (check + format), check-manifest, and mypy with a strict configuration (disallow_untyped_defs, disallow_untyped_calls, warn_redundant_casts) against both src and tests — a notably strict typing bar for a networking library.
API Design aiortc’s public surface deliberately tracks the JavaScript WebRTC API’s shape and naming (RTCPeerConnection, RTCSessionDescription, RTCIceCandidate, RTCDataChannel), substituting Python idioms — coroutines for promises, pyee events for EventTarget — so WebRTC’s substantial conceptual surface (SDP, ICE, DTLS, SCTP) transfers from browser experience rather than requiring a new mental model. The tradeoff is that getting a working connection still requires implementing your own signaling channel and understanding offer/answer semantics; the bundled examples (server, datachannel-cli, webcam) exist specifically to cover that gap, and Sphinx docs at aiortc.readthedocs.io document the full API with autodoc-generated references.