aiortc: WebRTC and ORTC Implementation for Python
raw JSON → 1.14.0 verified Sat Apr 25 auth: no python
aiortc is a Python library that provides an implementation of Web Real-Time Communication (WebRTC) and Object Real-Time Communication (ORTC). Built on Python's asynchronous I/O framework asyncio, it enables the exchange of audio, video, and data channels. The library's API closely mirrors its JavaScript counterpart, utilizing coroutines instead of promises and `pyee.EventEmitter` for event handling. Currently at version 1.14.0, aiortc is actively maintained with regular updates to support WebRTC specification changes and introduce new codecs or features, and its interoperability is regularly tested against Chrome and Firefox.
pip install aiortc Common errors
error fatal error C1083: The included file cannot be opened: 'libavutil/mathematics.h': No such file or directory ↓
cause This error occurs when the required FFmpeg development libraries are missing during the installation of aiortc.
fix
Install the FFmpeg development libraries appropriate for your operating system before installing aiortc.
error Uncaught TypeError: Cannot read property 'getUserMedia' of undefined ↓
cause This error occurs when attempting to access `getUserMedia` on an insecure origin, as browsers restrict this API to secure contexts.
fix
Serve your application over HTTPS or configure your browser to treat the origin as secure for development purposes.
error ValueError: None is not in list ↓
cause This error occurs when there is a mismatch in the SDP negotiation, often due to missing or incorrect media tracks.
fix
Ensure that both peers have matching media tracks and that the SDP negotiation process is correctly implemented.
error IndexError: list index out of range ↓
cause This error occurs when parsing an SDP answer that lacks expected SSRC attributes, leading to an attempt to access a non-existent list element.
fix
Verify that the SDP answer includes the necessary SSRC attributes and that the remote description is correctly set.
error ConnectionError: Cannot send encrypted data, not connected ↓
cause This error occurs when attempting to send data over an SCTP transport that is not fully established.
fix
Ensure that the SCTP transport is connected before sending data, and handle connection state changes appropriately.
Warnings
breaking The `RTCDataChannel.send` method has historically changed between being a regular function and a coroutine. While currently a coroutine, be aware of this breaking change if upgrading from older versions, particularly around 0.9.x. ↓
fix Ensure `await` is used when calling `RTCDataChannel.send()` if you are on a version where it's a coroutine. Review the changelog for specific version behavior.
breaking Older Python versions are no longer supported. aiortc dropped support for Python 3.5 (0.9.23), 3.6 (1.3.0), and 3.8 (1.10.0). ↓
fix Ensure your environment uses Python 3.10 or newer to be compatible with the latest aiortc releases.
gotcha When using `MediaRecorder` with `PyAV` for video, the default resolution can be hardcoded to 640x480, and `aiortc` might not automatically adjust it. This can lead to unexpected video sizes if not explicitly handled. ↓
fix Explicitly configure the video size when initializing `MediaPlayer` or `MediaRecorder` if a different resolution is desired.
gotcha For outgoing media tracks, it is crucial to establish and add the track to the `RTCPeerConnection` *before* the server sends back the ICE response during the signaling process. Failing to do so can result in the peer connection opening in a 'recvonly' mode, preventing the sending of media. ↓
fix Ensure your signaling logic properly synchronizes the addition of outgoing tracks with the exchange of ICE candidates and SDP answers.
gotcha The `MediaRecorder` consumes incoming tracks and does not natively manage presentation timestamp (PTS) gaps caused by network interruptions. Directly recording an incoming track with `MediaRecorder` can lead to reception halting if there are PTS discontinuities. ↓
fix For scenarios requiring robust recording of incoming tracks while also re-transmitting them, use a `MediaRelay` to duplicate the track and feed one stream to the `MediaRecorder` and the other to the outgoing peer connection. Implement custom logic to handle PTS adjustments if direct recording of lossy streams is necessary.
Install
pip install aiohttp aiortc opencv-python Install compatibility last tested: 2026-04-25
runtime status import time mem disk
3.10-alpine — — —
3.10-alpine 0.73s 14.4MB 155.6M
3.10-slim 0.68s 14.8MB 430M
3.10-slim 0.74s 14.4MB 160M
3.11-alpine — — —
3.11-alpine 1.42s 16.2MB 160.5M
3.11-slim 1.03s 16.6MB 441M
3.11-slim 1.21s 16.2MB 166M
3.12-alpine — — —
3.12-alpine 1.26s 16.3MB 153.3M
3.12-slim 1.49s 16.6MB 431M
3.12-slim 1.63s 16.2MB 159M
3.13-alpine — — —
3.13-alpine 1.22s 16.7MB 152.3M
3.13-slim 1.24s 17.5MB 429M
3.13-slim 1.55s 16.7MB 157M
3.9-alpine — — —
3.9-alpine — — —
3.9-slim — — —
3.9-slim — — —
Imports
- RTCPeerConnection
from aiortc import RTCPeerConnection - RTCSessionDescription
from aiortc import RTCSessionDescription - RTCConfiguration
from aiortc import RTCConfiguration - MediaStreamTrack
from aiortc.mediastreams import MediaStreamTrack - VideoStreamTrack
from aiortc.mediastreams import VideoStreamTrack - AudioStreamTrack
from aiortc.mediastreams import AudioStreamTrack - RTCDataChannel
from aiortc import RTCDataChannel - RTCCertificate
from aiortc import RTCCertificate - generateCertificate
from aiortc import RTCCertificate, generateCertificate - MediaRelay wrong
from aiortc import MediaRelaycorrectfrom aiortc.contrib.media import MediaRelay - MediaPlayer wrong
from aiortc import MediaPlayercorrectfrom aiortc.contrib.media import MediaPlayer
Quickstart
import asyncio
from aiortc import RTCPeerConnection, RTCSessionDescription
async def main():
pc = RTCPeerConnection()
print("RTCPeerConnection created.")
# Example: Create an offer (typically this is exchanged via a signaling server)
offer = await pc.createOffer()
await pc.setLocalDescription(offer)
print(f"Local SDP Offer:\n{pc.localDescription.sdp}")
# In a real application, you'd send pc.localDescription to a remote peer
# and receive their answer, then set it as remoteDescription.
# For this quickstart, we'll simulate a minimal answer (not fully functional for media).
# Simulate receiving an answer (replace with actual signaling in a real app)
# For a real peer, this would be generated by the remote peer's createAnswer()
# and contain media tracks if applicable.
# remote_sdp_answer = "v=0\r\no=- 12345 12345 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=fingerprint:sha-256 A0:B1:C2:D3:E4:F5:G6:H7:I8:J9:K0:L1:M2:N3:O4:P5:Q6:R7:S8:T9:U0:V1:W2:X3:Y4\r\na=group:BUNDLE audio video\r\na=msid-semantic:WMS\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\na=rtcp-mux\r\na=rtpmap:111 OPUS/48000/2\r\na=mid:audio\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\na=rtcp-mux\r\na=rtpmap:96 VP8/90000\r\na=mid:video\r\n"
# remote_description = RTCSessionDescription(sdp=remote_sdp_answer, type="answer")
# await pc.setRemoteDescription(remote_description)
# print("Remote SDP Answer set (simulated).")
# Keep the connection alive for a short period or until closed by events
try:
while pc.connectionState != "closed" and pc.connectionState != "failed":
await asyncio.sleep(1)
except asyncio.CancelledError:
pass
finally:
print("Closing peer connection...")
await pc.close()
print("Peer connection closed.")
if __name__ == "__main__":
# Ensure auth check passes for quickstart (not applicable for aiortc directly)
# For real use cases, replace os.environ.get with actual credentials if needed by signaling.
# Example: if you had a signaling server requiring a token:
# import os
# if not os.environ.get('WEBRTC_AUTH_TOKEN'):
# print("Warning: WEBRTC_AUTH_TOKEN not set. Quickstart might fail in a real scenario.")
asyncio.run(main())