/ concept-collection / commonroom
Sign in
concept-collection / commonroom
commonroom / README.md
64 lines · 3.1 KBPreviewCodeBlameHistoryRaw
1# commonroom
3Serverless group video calls in the browser.
5**Live page:** https://concept-collection.github.io/commonroom/
7Enter your name and a room name — any string you like (no spaces) — and you're
8in. Share the room URL with anyone; everyone who joins the same room is
9connected to everyone else over a full WebRTC mesh, up to 8 people. You enter
10with your microphone and camera **off** and turn them on when you're ready.
11Click any tile to enlarge it (the rest shrink to a filmstrip); click it again
12or press Esc to return to the gallery.
14The room has shared settings that anyone can change and that apply to
15everyone — currently the video quality (low / medium / high / auto, medium by
16default). You can also share your screen in place of your camera, and there's
17a room chat (with join/left notices and clickable links) that is as ephemeral
18as the call itself: you only see what's said while you're in the room, and
19nothing is stored anywhere.
21## How it works
23There is no backend and no room registry. The techniques come from the sibling
24projects [commonview](https://github.com/concept-collection/commonview) (the
25auto-connecting mesh) and
26[commoncall](https://github.com/concept-collection/commoncall) (WebRTC media,
27quality presets, screen share):
29- **Identity** — each browser generates a secp256k1 (BIP340 schnorr) keypair,
30 persisted in localStorage. The x-only public key is the peer ID, and every
31 nostr event is signed with it, so peers can't be impersonated.
32- **Rooms** — the room name is hashed into a nostr topic; knowing the name IS
33 the key. Everyone in the room announces `{peerId, name}` on that topic every
34 few seconds via ephemeral events on public relays; entries expire when
35 announcements stop.
36- **Mesh** — being in the room is the consent: every participant automatically
37 brings up a WebRTC connection with every other participant (deterministic
38 initiator = smaller peer ID; offer/answer/ICE ride per-peer nostr topics).
39 Audio/video flows directly between browsers, with public STUN servers and a
40 free TURN relay as fallback. Rooms are softly capped at 8 — peers already at
41 capacity turn newcomers away.
42- **Muted by default** — camera/mic are requested on entry so unmuting is
43 instant, but tracks start disabled. If you deny access you still join,
44 sending silent/black placeholder tracks; unmuting retries the device and
45 upgrades the track in place (`replaceTrack`, no renegotiation).
46- **Shared settings** — one settings object for the whole room, synced over
47 the per-peer control data channels with per-key last-writer-wins (revision
48 counters; ties resolved by the setter's peer ID). The video-quality presets
49 map to `RTCRtpSender.setParameters` caps that each participant applies to
50 its own outgoing senders.
52## Development
54```sh
55npm install
56npm run dev
57```
59Identity is per-browser-profile (localStorage), so two tabs in the same
60profile are the *same* peer — to try a room with multiple participants, use a
61second browser or a private window.
63`npm run build` type-checks and bundles to `dist/`. Pushes to `main` deploy to
64GitHub Pages via `.github/workflows/deploy.yml`.
moveopenescclose