aiortc: WebRTC and ORTC Implementation for 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.
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.
- 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).
- 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.
- 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.
- 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.
Install
-
pip install aiortc -
pip install aiohttp aiortc opencv-python
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
from aiortc.contrib.media import MediaRelay
- MediaPlayer
from 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())