Cloudflare Realtime WebRTC <-> WebSocket Bridge - Technical Demo

This demo shows a WebSocket Relay (on this Worker) and its use with the Cloudflare Realtime API for WebRTC <-> WebSocket bridging. Replace {appId} below with your Cloudflare Realtime App ID.

Part 1: The WebSocket Relay (This Worker)

This Worker relays WebSocket messages: receives on /publish for a channel, and broadcasts to all /subscribe clients on the same channel.

Use this Relay:

This relay is unaware of WebRTC or the Cloudflare Realtime API.

Part 2: Bridging with Cloudflare Realtime API

The Cloudflare Realtime API (a separate production service) can bridge WebRTC and WebSockets via its endpoint: https://rtc.live.cloudflare.com/v1/apps/{appId}/adapters/websocket/new

General API Request Body structure to /adapters/websocket/new:

{
    "tracks": [{
        "location":    "'local' or 'remote'",
        "sessionId":   "your_session_id",
        "trackName":   "your_track_name",
        "endpoint":    "target_websocket_url",
        // "outputCodec" or "inputCodec": "pcm" (see note below)
    }]
}

Note: The codec field is 'outputCodec' for 'location: "remote"' and 'inputCodec' for 'location: "local"'. See scenarios.

location parameter & sessionId behavior (user's perspective):

SCENARIO A: Send Existing WebRTC Track Audio TO a "Remote" WebSocket Endpoint

(Realtime API: WebRTC Track → "Remote" WebSocket)

  1. A WebRTC source (e.g., /publisher app) publishes mic-track to your Realtime session (e.g., session-abc).
  2. To send mic-track's audio out, POST to https://rtc.live.cloudflare.com/v1/apps/{appId}/adapters/websocket/new with:
    { "tracks": [{ "location": "remote",
                       "sessionId": "session-abc",
                       "trackName": "mic-track",
                       "endpoint": "wss://bridge.orange.cloudflare.dev/ws/<channel>/publish",
                       "outputCodec": "pcm" }] }
    (Note the use of outputCodec for location: "remote".)
  3. This demo relay (acting as the "remote" WebSocket endpoint) receives audio on its /publish URL and broadcasts it to its /subscribe URL.
  4. WebSocket clients (e.g., /player app) connect to the relay's /subscribe URL to get the audio.

ASCII Diagram for SCENARIO A:

  [WebRTC Source] ---WebRTC---> [Cloudflare Realtime API Session (ID: session-abc)]
    (e.g., Mic,                      (Has existing 'mic-track')
     /publisher app)                          |
                                              | API Call: POST to `https://rtc.live.cloudflare.com/v1/apps/{appId}/adapters/websocket/new`
                                              |  - location: 'remote'
                                              |  - sessionId: 'session-abc' (REQUIRED)
                                              |  - trackName: 'mic-track'
                                              |  - endpoint: Demo Relay's /publish URL
                                              |  - outputCodec: 'pcm'
                                              V
  [Demo Relay (This Worker): wss://bridge.orange.cloudflare.dev/ws/<channel>/publish] <---(WebSocket: audio data from Realtime)---
   (Acts as "Remote" WebSocket Endpoint for Realtime)   |
                                                        | (WebSocket: audio data broadcast by Relay)
                                                        V
          [Demo Relay (This Worker): wss://bridge.orange.cloudflare.dev/ws/<channel>/subscribe]
                                                        |
                                                        | (WebSocket: audio data)
                                                        V
                                             [WebSocket Listeners]
                                               (e.g., /player app)
        

SCENARIO B: Create WebRTC Track FROM Audio at a "Local" WebSocket Endpoint

(Realtime API: "Local" WebSocket → New WebRTC Track with New Session)

  1. An audio source sends audio to this demo relay's /publish URL.
  2. The demo relay broadcasts this audio to its /subscribe URL. This /subscribe URL will act as the "local" WebSocket endpoint for Realtime.
  3. To create a WebRTC track from this audio, POST to https://rtc.live.cloudflare.com/v1/apps/{appId}/adapters/websocket/new with:
    { "tracks": [{ "location": "local",
                       // "sessionId": "any_value_is_ignored",
                       "trackName": "new-track-from-ws",
                       "endpoint": "wss://bridge.orange.cloudflare.dev/ws/<channel>/subscribe",
                       "inputCodec": "pcm" }] }
    (Note the use of inputCodec for location: "local". The API will generate a NEW sessionId for this track, returned in the response.)
  4. Realtime connects to the endpoint, ingests audio, creates new-track-from-ws, and associates it with a NEWLY GENERATED sessionId.
  5. WebRTC clients (e.g., /pull app) use the sessionId returned in the API response from step 3 to subscribe to new-track-from-ws in Realtime.

ASCII Diagram for SCENARIO B:

  [WebSocket Audio Source] --WebSocket--> [Demo Relay (This Worker): wss://bridge.orange.cloudflare.dev/ws/<channel>/publish]
   (e.g., backend script)                    (Receives audio)
                                                       |
                                                       | (WebSocket: audio data broadcast by Relay)
                                                       V
  [Demo Relay (This Worker): wss://bridge.orange.cloudflare.dev/ws/<channel>/subscribe]
   (Acts as "Local" WebSocket Endpoint for Realtime)     |
                                                         | (WebSocket: audio data for Realtime to ingest)
                                                         |
                                                         | API Call: POST to `https://rtc.live.cloudflare.com/v1/apps/{appId}/adapters/websocket/new`
                                                         |  - location: 'local'
                                                         |  - sessionId: (IGNORED - API generates NEW one)
                                                         |  - trackName: 'new-track-from-ws'
                                                         |  - endpoint: This Relay's /subscribe URL
                                                         |  - inputCodec: 'pcm'
                                                         V
                                          [Cloudflare Realtime API (Generates NEW Session)]
                                                         |  (API Response includes the new sessionId)
                                                         |
                                                         | (Creates 'new-track-from-ws'; associates with NEW sessionId)
                                                         |
                                                         | (WebRTC: audio from 'new-track-from-ws')
                                                         V
                                              [WebRTC Listeners (use new sessionId from API response)]
                                                (e.g., /pull app)
        

Demo Web Apps (on This Worker)

This page is provided strictly for demo purposes with no support nor warranty. If you are a Cloudflare Realtime customer, please talk to your Cloudflare account team or point of contact about supporting your use case with the production Cloudflare Realtime service.