/realtime - WebRTC Support
Connect to the Realtime API via WebRTC from browser/mobile clients. LiteLLM handles auth; audio streams directly to OpenAI/Azure.
Providers: OpenAI ยท Azure
WebRTC vs WebSocket
- WebSocket (
/v1/realtime) โ server-to-server - WebRTC (
/v1/realtime/client_secrets+/v1/realtime/calls) โ browser/mobile, lower latency
How it worksโ
LiteLLM issues tokens and relays SDP; audio never passes through the proxy.
Browser LiteLLM Proxy OpenAI/Azure
| | |
|-- POST client_secrets --->|-- POST sessions -------->|
|<-- encrypted_token -------|<-- ek_... ---------------|
|-- POST calls [SDP+token] ->|-- POST calls ----------->|
|<-- SDP answer ------------|<-- SDP answer -----------|
|===== audio P2P direct ===============================>|
Proxy Setupโ
model_list:
- model_name: gpt-4o-realtime
litellm_params:
model: openai/gpt-4o-realtime-preview-2024-12-17
api_key: os.environ/OPENAI_API_KEY
model_info:
mode: realtime
Azure: model: azure/gpt-4o-realtime-preview, api_key, api_base.
litellm --config /path/to/config.yaml
Client Usageโ
- Token โ
POST /v1/realtime/client_secretswith LiteLLM key and{ model }. - WebRTC โ Create
RTCPeerConnection, add mic, data channeloai-events, send SDP offer toPOST /v1/realtime/callswithAuthorization: Bearer <token>,Content-Type: application/sdp. - Events โ Use data channel for
session.updateand other events.
const r = await fetch("http://proxy:4000/v1/realtime/client_secrets", {
method: "POST",
headers: { "Authorization": "Bearer sk-litellm-key", "Content-Type": "application/json" },
body: JSON.stringify({ model: "gpt-4o-realtime" }),
});
const token = (await r.json()).client_secret.value;
const pc = new RTCPeerConnection();
const audio = document.createElement("audio");
audio.autoplay = true;
pc.ontrack = (e) => (audio.srcObject = e.streams[0]);
const ms = await navigator.mediaDevices.getUserMedia({ audio: true });
pc.addTrack(ms.getTracks()[0]);
const dc = pc.createDataChannel("oai-events");
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const sdpRes = await fetch("http://proxy:4000/v1/realtime/calls", {
method: "POST",
headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/sdp" },
body: offer.sdp,
});
await pc.setRemoteDescription({ type: "answer", sdp: await sdpRes.text() });
dc.send(JSON.stringify({ type: "session.update", session: { instructions: "..." } }));
FAQโ
- 401 Token expired โ Get a fresh token right before creating the WebRTC offer.
- Which key for
/calls? โ Encrypted token fromclient_secrets, not raw key. - Pass
model? โ No. Token encodes routing. - Azure
api-versionโ Setapi_versioninlitellm_paramsand correctapi_base. - No audio โ Grant mic; ensure
pc.ontracksets autoplay audio; check firewall/WebRTC; inspect console.