mats 25bc94a3a1
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 11m6s
restore browser video codec defaults
2026-09-22 17:37:47 +02:00
2026-09-22 16:49:40 +02:00
2026-09-22 17:37:47 +02:00
pwa
2026-09-22 13:55:06 +02:00

gibbz voice — POC

Discord-clone proof of concept: peer-to-peer WebRTC voice chat + screen sharing with position-based spatial audio and pluggable STUN/TURN.

Run (Node 18+, only dep is ws):

npm install
PORT=8081 npm start
# open http://localhost:8081, click a voice channel, allow mic

What works

  • Mesh WebRTC voice (perfect negotiation; lowest peer id initiates)
  • Screen share with audio (mic is spatialized, screen audio plays direct)
  • Spatial audio: drag your avatar on the plane; remote mics run through a PannerNode (HRTF, inverse distance). Positions sync over signaling.
  • Custom STUN/TURN: gear icon → JSON override in localStorage, applied on next join. Server default comes from env (below).
  • Mute (M), deafen (D), per-peer volume, speaking indicators.
  • Voice capture uses mono 48 kHz Opus-oriented settings, a 64 kbps audio ceiling, and periodic packet-loss, jitter, and RTT quality diagnostics.
  • Audio input has manual gain control and a live signal/clipping meter in the settings dialog; microphone processing is split into public/audio-manager.js.
  • Screen sharing uses the browser's default codec negotiation, with selectable detail (text/UI) or motion (gameplay) content hints.

ICE configuration (server side)

Env var Meaning
STUN_URLS comma-separated stun: urls (Google defaults)
TURN_URLS comma-separated turn:/turns: urls
TURN_USERNAME / TURN_CREDENTIAL static TURN creds
ICE_TRANSPORT_POLICY WebRTC ICE policy: all, relay, or none
ICE_SERVERS_JSON full {"iceServers":[...]} override, wins over the above
PORT / HOST listen address (default 8081 / 0.0.0.0)

Example with coturn:

TURN_URLS='turn:turn.example.com:3478?transport=udp,turns:turn.example.com:5349' \
TURN_USERNAME=mats TURN_CREDENTIAL=secret npm start

For deployments where clients are commonly behind separate NATs, set ICE_TRANSPORT_POLICY=relay so media consistently uses the public TURN service instead of depending on NAT hairpinning or direct candidate pairs.

POC shortcuts (productionize later)

  • No auth, no reconnection, rooms are in-memory, signaling is unencrypted ws behind the preview ingress (use wss/TLS in front for real deploys).
  • No media server: N² mesh — fine for small rooms, needs SFU (mediasoup/livekit) beyond ~6–8 participants.
  • For larger rooms or consistently lower bandwidth, replace the mesh with an SFU; the current quality tuning improves the P2P path but does not change its N² cost.
  • Text channels are decorative. No persistence, no rate limiting.
  • Screen-share negotiation storms on join/leave are expected at small scale.
S
Description
No description provided
Readme
38 MiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 75.1%
CSS 16.2%
HTML 7.5%
Makefile 0.9%
Dockerfile 0.3%