Streaming overlay for the Game scene. Reads the manifest written by
loading.sh (game name, subtitle, mic state) and pulls live state from
OBS WebSocket on the same connection that delivers music updates.
- Top HUD: TRANSMISSION ID / SIGNAL bars / UTC clock — same vibe as
Landing/Loading, sized smaller so it doesn't dominate the gameplay.
- Camera frame (top-right, 480×270 with cyan corner ticks): decorative
drop-target. The actual OBS camera source layers ON TOP; a centered
placeholder (camcorder SVG + 'PLACE CAMERA HERE' + frame coordinates
'2008, 100 · 480×270') shows during setup and gets covered when the
camera source is positioned. Configurable via URL params:
?camera=Webcam&scene=Game.
- Status bar (bottom): solid gradient + cyan top edge so it reads on
any gameplay background. Two lines:
LIVE · GAME · SUBTITLE
elapsed timer · mic state · now-playing track
- Live camera-frame sync: queries GetSceneItemEnabled on connect and
subscribes to SceneItemEnableStateChanged, so toggling the camera's
eye-icon in OBS hides/shows the frame within ~50ms — overrides the
manifest's static value.
- Music sync: shares the same WS connection; now-playing line updates
from mpd:state broadcasts.
- CRT overlays kept lighter than Landing (gameplay must remain readable).
Music persistence across scene switches by extracting playback into a
separate browser source (music/index.html) — single source instance
shared across scenes via OBS's "Add Existing", so it doesn't restart on
scene change.
Loading and Game overlays subscribe to mpd:state CustomEvents over OBS
WebSocket; the daemon broadcasts at 1 Hz plus on every track change.
File-based command pipeline lets bash control playback without a
WebSocket client of its own:
- vendor/obs-ws-mini.js — minimal WS v5 client with HMAC-SHA256 auth,
hard timeout, close-rejection, and a pure-JS SHA-256 fallback for
CEF file:// origins where crypto.subtle is unavailable.
- setup.sh — generates vendor/obs-config.js from the OBS plugin config;
checks the live socket instead of the (lagging) config file.
- music/index.html — invisible audio worker. Plays through a shuffled
queue with hardened error/stall recovery, polls loading/cmd.js for
bash-issued commands, broadcasts mpd:state via WS. Includes a
diagnostic status block (visible if the source's eye-icon is on).
- loading/index.html — strips local audio playback; subscribes to
mpd:state to drive the now-playing terminal line live. Removes the
redundant trailing prompt; terminal lines anchor at the bottom.
- loading/playlist.sh — rebuilt as subcommand API:
sync (default), skip, prev, pause, resume, status
control commands write loading/cmd.js (id, type, ts), which the
daemon polls every 250ms.
- loading/convert.sh — strips video tracks from .webm music downloads
to audio-only m4a (~95% smaller, ~20× faster decode); fixes the
CPU pegging from CEF decoding 1080p VP9 video for music playback.
- .gitignore — track manifests, ignore generated wrappers + secrets +
the audio cache.