You already run a custom WebSocket audio bridge. It is a service that carries raw audio frames over a WebSocket. It sits between a browser/app and your AI backend, or between a telephony/agent vendor and your orchestrator. This page shows how to put that WebSocket audio source in front of ClutchCall Voice’s QUIC transport, media plane, and telephony. You do not rewrite your audio backend. The short version: the concrete adapter that ships today is a PCM16 WebSocket proxy. It is the same proxy that backs the Vapi vendor bridge. Your backend plugs in as the WebSocket peer that the proxy decodes to and re-encodes from. ClutchCall owns the customer-facing transport (QUIC/WebTransport, with a WebSocket fallback). ClutchCall also does the Opus ⇄ PCM16 codec work. Your WebSocket bridge stays a PCM16 audio endpoint.
What has a ready adapter. Vapi’s PCM16 WebSocket shape is wired in the vendor bridge. LiveKit uses the same bridge as an Opus passthrough. Twilio Media Streams is a different path. Mulaw over WebSocket maps to a codec-passthrough SIP trunk, not this proxy. See /modalities/voice/migration/from-twilio.

Which shape of WebSocket bridge do you have?

“Custom WebSocket audio” covers two very different edges. They map onto different ClutchCall on-ramps. Pick the edge that matches yours before you migrate.

Backend-edge WebSocket

A vendor or telephony provider streams audio to your AI orchestrator over a WebSocket. The format is typically PCM16 (Vapi-style) or mulaw (Twilio-style). Your backend consumes and produces raw audio frames. → Map this onto the PCM16 WebSocket proxy below.

Client-edge WebSocket

A browser or app streams captured audio to your backend over a WebSocket, because it cannot open a raw media socket. → Adopt the engine’s WebSocket media fallback and let the SDK own capture. See Browser/app clients.

The adapter that exists: a PCM16 WebSocket proxy

The vendor bridge is a WebTransport handler. It sits between a customer media leg and an external audio backend reached over a secure WebSocket. For the Vapi shape, the flow is:
1

Customer audio arrives over QUIC/WebTransport

A caller (browser, app, or a bridged phone leg) reaches the engine over QUIC/WebTransport. When UDP is blocked, the caller reaches the engine over the WebSocket fallback. Audio is framed Opus on that customer leg.
2

The bridge transcodes to PCM16 and cleans it

On ingress, the bridge decodes Opus and resamples to 16 kHz PCM16. It then runs noise suppression. Thus your backend receives clean, uncompressed audio. This is also why the cleanup lives at the edge and not in your service. The bridge then sends raw PCM16 to your WebSocket backend as binary messages.
3

Your backend replies in PCM16

Your backend (the “sidecar”) speaks its vendor’s PCM16 WebSocket protocol. It publishes the caller into your agent. It streams the agent’s PCM16 audio back over the same socket.
4

The bridge re-encodes to the caller

The bridge re-chunks the return PCM16 into 20 ms frames, encodes them as Opus, and writes them back to the customer leg. Your backend never touches Opus, QUIC, or SRTP.
The WebSocket backend that terminates the PCM16 stream (the “sidecar”) is external to the engine. It uses the vendor’s API to publish/subscribe. The in-tree bridge provides the transport, the codec transform, the framing, and the denoise. You (or the vendor’s cloud) provide the PCM16 WebSocket peer. You supply the vendor selection and credentials as deployment configuration today. Per-tenant hydration from the connection token is a follow-on.

Map your custom source onto the proxy

Your job is to make your existing WebSocket audio backend look like the PCM16 peer that the bridge already knows. There are three cases, easiest first.
1

If your backend already speaks Vapi's PCM16 framing

Point the vendor bridge at Vapi (VENDOR = vapi) and supply your VAPI_API_KEY. The bridge’s PCM16 branch handles the codec transform end to end. No engine changes are needed. This is the turnkey path.
2

If your backend speaks a generic PCM16 WebSocket

Conform your endpoint to the PCM16 sidecar contract: accept and emit 16 kHz mono PCM16 as binary WebSocket messages, one media leg per connection. The bridge treats it like the Vapi PCM16 branch.
The shipped bridge branches on two codecs only: PCM16 (Vapi shape) and Opus passthrough (LiveKit shape). A framing that is neither is not a turnkey branch yet. Conform to the 16 kHz PCM16 contract. Or treat the bridge as a reference and adapt at your sidecar. Do not expect the engine to speak your custom framing.
3

Route inbound phone calls straight at your WebSocket backend

For PSTN/SIP trunks, set the trunk’s inbound AI WebSocket URL (inbound_ai_websocket_url) to your endpoint. Inbound calls that match that trunk get their AI leg bridged to your WebSocket after the more specific routes are exhausted. The route order is:
  1. An explicit agent binding.
  2. A skill/queue target.
  3. The QUIC bridge URL.
  4. This WebSocket URL.
Pair it with inbound_ai_quic_url if you also expose a QUIC endpoint.

Browser/app clients

Your custom WebSocket bridge can really be a client transport: a browser or app that ships captured audio to a backend. In that case, you usually do not need a bespoke socket at all. The engine serves a WebSocket media fallback (subprotocol clutch-media). It carries the identical browser ⇄ agent audio leg for clients on networks where QUIC/UDP is blocked (Safari, strict corporate firewalls). It uses the ws/<sid> namespace. Thus it never collides with the WebTransport leg’s wt/<sid>. The wire is framed Opus in both directions.
The QUIC → WebSocket automatic fallback ladder ships in the native SDK cores only. The browser/TypeScript SDK is WebTransport-only today. Thus a browser client either uses WebTransport, or targets the clutch-media endpoint with the framed-Opus wire directly. Plan your browser rollout around WebTransport support. See /modalities/voice/transport-web/browser-compatibility.
Let the SDK own capture (device AEC/AGC/noise suppression, Opus encode, the media-over-QUIC track). Do not re-implement capture in your WebSocket client. See /modalities/voice/transport-web/browser-audio-capture.

Wire and audio contract

  • Customer leg (WebTransport or clutch-media WebSocket): an optional handshake, then length-prefixed frames [u32 BE length][Opus payload] in both directions.
  • Sidecar leg (PCM16 backends, e.g. Vapi): 16 kHz mono PCM16 as binary WebSocket messages. LiveKit-shape backends instead get raw Opus passthrough.
  • Engine agent bus: 8 kHz PCM16 end to end. The bridge resamples between 8/16/48 kHz as needed. Phone legs are G.711 (µ-law/A-law) on the wire. The engine transcodes them internally.
  • Namespaces: WebTransport legs use wt/<sid>. The WebSocket fallback uses ws/<sid>. The audio-only track model is in /modalities/voice/concepts/sessions-calls-tracks-streams.

Keep your existing runtime

When the vendor bridge — not a native pipeline — is the right home for your audio backend.

Custom runtime integration

Bring your own realtime endpoint through the provider abstraction.

From Twilio Media Streams

Mulaw-over-WebSocket → codec-passthrough SIP trunk, the other WebSocket path.

Migration overview & checklist

The full cut-over sequence for trunks and agents that you point at ClutchCall.