:443 connection to
relay.clutchcall.dev. This is the same track substrate as every other leg of
the call (voice/<sid>/{uplink,downlink}). There is no media SFU and no
gateway round-trip on the audio path.
The transport ladder
The standing design is a ladder: QUIC/MoQT is first-class, with WebSocket (control/data) and WebRTC (media) as the fallbacks for networks where UDP is blocked or a browser lacks WebTransport. Know where each rung ships today. The ladder is complete in the native SDK cores, but the browser/TypeScript SDK is WebTransport-only right now.On the browser today, if the QUIC/WebTransport path is unavailable, the SDK
does not silently downgrade to WebSocket or WebRTC media. That rung is not
yet shipped for the TypeScript client. The QUIC→WebSocket fallback ladder
currently lives only in the native SDK cores. Plan browser deployments for a
WebTransport-capable, UDP-reachable network. See
Browser compatibility
for the gate and the current matrix.
WebTransport: the browser-native QUIC path
WebTransport gives the browser a real QUIC connection; you run no UDP plumbing. The SDK’sMoqtClient dials relay.clutchcall.dev, negotiates the
moqt-16 subprotocol, and returns immediately. It queues your publishes and
subscribes and replays them once the session is up. It then auto-reconnects
with capped backoff if the link drops. Audio then flows as MoQT objects on the
call’s two tracks:
serverCertificateHashes, and the 127.0.0.1
local-dev gotcha live in WebTransport.
Reusing the browser’s audio pipeline (WebRTC diversion)
Browser voice sounds good because you keep the browser’s audio pipeline but not its transport. A loopbackRTCPeerConnection runs the browser’s capture
graph: echo cancellation, gain control, noise suppression, the Opus encoder,
and the jitter buffer. An
RTCRtpScriptTransform
that runs in a Worker taps the encoded Opus frames and hands them to MoQT.
The WebRTC ICE/DTLS/SRTP transport is never used; only its codec and processing
are. Raw PCM never crosses the wire. Because the tap is at the encoded-frame
layer, the relay only ever sees opaque payloads.
1
Capture and encode
captureMicrophone(publication) requests the mic with AEC/AGC/NS enabled,
wires the loopback peer connection, and installs the Worker transform on
the sender. The browser’s Opus encoder then runs on your audio.2
Publish over QUIC/MoQT
The Worker reads each encoded frame off the transform’s readable stream and
writes it to
voice/<sid>/uplink as a MoQT object over WebTransport. The
relay fans it to whatever the engine bridged the call to — a SIP leg, an
agent, a recorder.3
Subscribe and play back
Downlink Opus arrives on
voice/<sid>/downlink. The SDK’s OpusPlayer
decodes it with WebCodecs and renders it through an audio-worklet ring
buffer. The buffer pads silence on underrun.Mobile apps
Native iOS/Android transport is planned, not shipped. There is no
Swift or Kotlin SDK today. The planned path is a portable QUIC/MoQT client
compiled through a shared C++ FFI (per-ABI
.so on Android, static .a on
iOS, and a .jslib shim for WebGL builds). To ship to phones now, run the app
inside a WebTransport-capable mobile browser view, or reach the engine through
a server-side leg. Track status in
Mobile app transport.Where to go next
WebTransport
The browser-native QUIC path — connect, subprotocol, dev certs, and the
track model in detail.
One-line WebRTC diversion
Divert an existing WebRTC audio pipeline onto QUIC with a single call.
RTCRtpScriptTransform
How the encoded-Opus tap works in a Worker, and why it is the only path.
Browser audio capture
Capture, encode, and publish mic audio — options, codecs, and playback.
Browser compatibility
What works where, the hard-gate, and the current fallback story.
Mobile app transport
The planned native path for carrying voice from iOS and Android apps.

