pi-webrtc

Architecture

這一頁還沒有中文版,以下顯示英文原文。

cf-sfu-worker is one Worker with three kinds of Durable Objects. This page shows what each part does, and what happens when someone watches a device.

flowchart LR
  P["Device"] -->|"1. POST /sfu/token"| W["Worker<br/>tokens, routing"]
  P -->|"2. WebSocket"| W
  V["Viewer"] -->|"1. POST /sfu/token"| W
  V -->|"2. WebSocket"| W
  W --> D["Device DO<br/>one per device"]
  W --> R["Room DO<br/>one per room"]
  D <-->|"members, watch, state"| R
  R -->|"room summaries"| G["Registry DO<br/>for the dashboard"]
  D -->|"the device's session"| S(("Realtime SFU"))
  R -->|"each viewer's session"| S
  P ==>|"media"| S
  S ==>|"media"| V

Parts

  • Worker (src/worker.ts): gives out tokens, checks them, and sends each socket to its Durable Object. It also serves the pages.
  • Device (src/server/device.ts): one per device_id. It holds the device's socket, its state, its SFU session, the rooms that watch it, and who controls it.
  • Room (src/server/room.ts): one per room_id. It holds the viewers' sockets, each viewer's SFU session, what each viewer pulls, the member devices, and the microphones.
  • Registry (src/server/registry.ts): one per worker. Each room reports to it, so the dashboard can list the rooms.

Each Durable Object keeps its state in its own SQLite storage. When two requests race, the object that owns the data decides. A restart or a deploy keeps the rooms, the viewers and the streams.

Idle devices cost little

The sockets use the WebSocket Hibernation API. The runtime answers ping by itself, so an idle device does not wake its Durable Object. Alarms check the heartbeats: every minute while someone watches, and every 5 minutes for a device that nobody watches.

Device states

stateDiagram-v2
  [*] --> offline
  offline --> sleeping: connects
  sleeping --> waking: a room gets a viewer (wake)
  waking --> live: ready
  waking --> sleeping: no ready, after two tries
  live --> sleeping: no viewers for 30 s (sleep)
  sleeping --> offline: socket closed or no ping
  live --> offline: socket closed or no ping

A device that reconnects with the same secret and generation stays live. Its stream keeps going.

Someone watches

sequenceDiagram
  participant V as Viewer
  participant R as Room DO
  participant D as Device DO
  participant P as Device
  participant S as Realtime SFU
  V->>R: WebSocket (token for lab-a)
  R->>D: watch(lab-a)
  D-->>P: wake
  R-->>V: joined (cam-1 waking)
  V->>R: offer (its own)
  R->>S: new session
  R-->>V: answer
  P->>D: offer (tracks)
  D->>S: push the tracks
  D-->>P: answer
  P->>D: ready
  D-)R: cam-1 is live
  R-->>V: device (cam-1 live)
  V->>R: subscribe (cam-1's tracks)
  R->>D: resolve (session, tracks)
  R->>S: pull the tracks
  R-->>V: offer
  V->>R: answer
  R->>S: renegotiate
  R-->>V: subscribed

The viewer's PeerConnection connects while the device wakes. So the video shows soon after the device is live.

The last viewer leaves

  1. The room tells the device that it no longer watches.
  2. When no room watches, the device waits 30 seconds. A new viewer in that time cancels it.
  3. The device gets sleep and closes its PeerConnection.

Reconnects

What happensResult
A device reconnects with the same secret and generationIt keeps its stream.
A device's socket dropsIt shows offline after 10 seconds, if it is not back.
A device's socket drops without a closeIt leaves its rooms after 60 seconds.
A device closes its socket normallyIt leaves its rooms at once.
A viewer reconnects within 30 secondsIt keeps its subscriptions and its control.
The worker is deployedEvery socket closes. Clients reconnect and keep their streams.

Code map

PathWhat it holds
src/worker.tsThe routes: token API, socket, dashboard, debug pages and pages
src/server/token.tsThe keys, and signing and checking tokens
src/server/device.tsThe Device Durable Object
src/server/room.tsThe Room Durable Object
src/server/registry.tsThe Registry Durable Object
src/server/realtime.tsCalls to the SFU and TURN APIs
src/server/socket.tsReading and writing frames
src/server/access.tsChecking Cloudflare Access sign-ins
src/server/config.tsSettings and fixed timings
src/shared/protocol.tsThe token request rules and the paths
demo/The scripts of the demo pages, bundled into public/sfu/js
public/sfu/The demo pages and the dashboard
tests/workerd/The tests
external/protocolThe protobuf messages (a git submodule)
在 GitHub 上編輯此頁

本頁內容