Your guests' cameras and screens, straight into OBS — peer to peer, self-hosted.
A guest opens a link, picks a camera or shares a screen, and their video goes browser to browser to your production machine. You see every guest with live latency and bitrate, and each one is a clean browser source for OBS, vMix or any tool that takes a URL.
| Page | Who | What |
|---|---|---|
/join/:room |
guest | camera or screen, device picker, noise removal, self view |
/director/:room |
producer | every guest as a tile: round-trip time, bitrate, mute, remove, copy scene link |
/scene/:room |
OBS | video only, transparent, no controls; ?only=<name> for one guest |
Media never touches the server. Signaling carries SDP and ICE candidates; TURN relays only for peers that cannot reach each other directly.
- Perfect negotiation, so a guest can switch camera mid-show without a reconnect.
- Hardware codecs first: H.264, then VP9, then VP8, per what the browser encodes in hardware.
- Bitrate caps per preset (1080p 6 Mbps, 720p 2.5, 360p 0.8) with
maintain-framerate, because a dropped frame is more visible than a soft one. - Noise removal with RNNoise compiled to WebAssembly, running in an AudioWorklet before audio leaves the guest.
- RTSP cameras join a room through go2rtc as ordinary guests.
docker run -d -p 6379:6379 redis:7
npm install
npm run dev # client on :3000, signaling on :4610Production: deploy/gke.md — Helm chart with the NestJS signaling (scaled, state in Redis), the static client behind Nginx ingress with Let's Encrypt, coturn on host networking with time-limited credentials, optional go2rtc, and a Prometheus ServiceMonitor with a Grafana dashboard.
client/ Create React App, styled-components
src/lib/ signaling socket, PeerLink (negotiation, codecs, stats), noise removal
src/pages/ Guest, Director, Scene
server/ NestJS
src/signaling/ WebSocket gateway and message schema
src/rooms/ Redis room state and cross-replica relay
src/turn/ coturn REST credentials
src/metrics/ Prometheus metrics, health
src/camera-bridge.ts
deploy/ Helm chart, GKE notes, Grafana dashboard
- RNNoise by Jean-Marc Valin, and the Jitsi team's WebAssembly build of it.
- go2rtc by Alexey Khit — the camera bridge would have been a month of work without it.
- The perfect negotiation pattern is straight from Jan-Ivar Bruaroey's write-up on the Mozilla blog and the WebRTC spec examples.
- coturn maintainers, for a TURN server that simply works.
AGPL-3.0-only. Run it for your show, change it, and share the changes if you offer it to others as a service.
