RTCPeerConnection
runs the browser’s real audio pipeline — echo cancellation, gain control, noise
suppression, and the Opus encoder — and an RTCRtpScriptTransform intercepts
the encoded Opus frames before they would be packetized. Those frames are handed
to the MoQT publication and shipped over QUIC/WebTransport. This page explains the
tap in depth: where it runs, why the older API is gone, and exactly how each frame
moves from the encoder to the wire.
For the one-call developer surface, see
One-Line WebRTC Diversion and
Browser Audio Capture.
This page is the mechanism underneath both.
The transform runs in a Worker — and only there
RTCRtpScriptTransform is the W3C Encoded Transform API. You construct it on the
main thread and attach it to an RTCRtpSender, but the transform callback itself
executes in a dedicated Worker. The SDK ships exactly one code path for tapping
encoded frames, and it is this Worker-based transform.
The older, Chromium-only
RTCRtpSender.createEncodedStreams() — which exposed the
encoded stream on the main thread — has been removed from current browser
engines, and the SDK has removed its legacy branch for it too. The Worker transform
is the sole encoded-frame path. There is no main-thread fallback.- It is what current browsers actually ship. Chrome 110+, Edge, Safari, and Firefox 133+ all expose the standard Worker transform; none still expose the main-thread stream. Targeting one API keeps the capture path identical everywhere.
- It is the seam for frame-level end-to-end encryption. Because every frame passes through one Worker, the SDK can later encrypt payloads there so that even a relay — or a self-hosted SFU you migrate off of — sees ciphertext only.
The hard gate: capture refuses when the transform is absent
The SDK treats the encoded-frame rule as non-negotiable. IfRTCRtpScriptTransform
is not a function on globalThis, the SDK refuses to capture rather than fall
back to an insecure or main-thread path. A helper reports support:
At capture time
captureMicrophone() checks support before calling getUserMedia, so it
never acquires hardware it cannot use. If unsupported it throws immediately.How a frame is tapped and forwarded
Once support is confirmed, the capture graph is a short loopback. The steps below trace one microphone frame from silicon to the QUIC wire.Run the browser audio pipeline in a loopback
Two
RTCPeerConnections are wired to each other locally (pc1 → pc2). Your
microphone track is added to pc1 as a sender; pc2 is only a sink so the
encoder is forced to run. The loopback SDP offer/answer is completed
locally — this is what starts the Opus encoder. WebRTC’s ICE/DTLS/SRTP
transport is never used to leave the machine.Attach the transform to the sender
A Worker is created and set as the sender’s From here, every encoded Opus frame the sender produces is routed into the
Worker instead of being packetized for WebRTC.
transform:Read frames off the transform inside the Worker
The Worker handles the The
rtctransform event. Each transformer exposes a
readable (incoming encoded frames) and a writable (the onward pipeline).
The Worker loops: read a frame, copy its payload, post it to the main thread,
then re-enqueue the frame to writable so the sender pipeline stays
unblocked.timestamp on each frame is the RTP timestamp on Opus’s 48 kHz clock.What crosses the wire
The transform hands off encoded Opus payloads, not PCM and not RTP packets. On the wire the Opus staysopus/48000/2 with a 48 kHz RTP clock even though the
encoder’s internal rate is driven narrowband for voice. The receiver side reverses
this: an Opus decoder (WebCodecs) feeds an audio worklet ring buffer — see the
OpusPlayer covered in
Browser Audio Capture.
Teardown
The handle returned by capture tears down the graph deterministically: it terminates the Worker, stops the microphone track (unless you supplied your own), and closes both loopback peer connections. It does not close the MoQT publication — that lifecycle is yours to manage on the transport.Lifecycle at a glance
Related
One-Line WebRTC Diversion
The developer-facing wrapper that hides this whole graph behind one call.
Browser Audio Capture
captureMicrophone, the OpusPlayer, and end-to-end capture wiring.Browser Compatibility
Which engines ship the transform, and where capture is refused.
WebTransport
The browser-native QUIC plane the tapped frames ride on.