Dynamic overlays
The document-based renderer, live data flow, permissions, scene selection and broadcast lifecycle.
How the system works
An overlay belongs to a tournament and stores a default canvas size, permission defaults, an active scene and a collection of scene and reusable component documents. Every document contains positioned nodes. The browser renderer loads one scene, resolves reusable components, subscribes to overlay socket state and renders tournament, match, pool and TournamentAssistant data.
Tournament + selected match + pool/flow + TA runtime
↓
overlay websocket snapshot
↓
scene document → reusable components → nodes
↓
browser source / desktop output / SpoutThe runtime resolves active TA participants against the selected BeatKhana match by platform ID; it does not rely on the retired isCurrentlyPlaying flag. Live TA telemetry and persisted BeatKhana match results are different data sources.
Data and render lifecycle
The viewer first downloads the overlay and requested scene, sorts visible nodes by z-index, resolves component instances and opens only the realtime feeds required by those nodes. BeatKhana socket events update the document tree and match data. TournamentAssistant supplies current map, player identity and live gameplay telemetry. The donation socket and Lightshow Showcase state are subscribed only when a component needs them. Replay score and lightshow subscriptions are shared at scene level rather than repeated per node.
Template values are calculated at render time from the node's inherited or fixed team, player, map and action binding. Missing data becomes an empty string or the documented preview fallback. See all components and the complete placeholder reference.
Native synchronized replay compositor
Fixed-window and Spout outputs add nativeOutput=window or nativeOutput=spout. When a native scene contains at least two compatible Replay Stream Player nodes that use the same ChroViewer origin, the renderer automatically replaces their independent WebGL iframes with one transparent ChroViewer compositor:
- one WebGL context, canvas, animation loop and GPU submission stream render all POV tiles;
- every tile retains its exact scene x/y/width/height, so normal dragging and resizing continue to work;
- ordinary overlay nodes at the same or higher z-index remain DOM layers above the canvas;
- each player has an independent replay session, camera, score timeline and viewport, but map files and extracted source data are shared;
- one audible POV owns song/hitsound decoding; the scene renderer remains audible in both window and Spout modes;
- the compositor elects an audible POV (otherwise the first ready POV) as the clock authority, checks the other streams every 50 ms and seeks a stream when same-map drift exceeds 40 ms, with a 500 ms correction cooldown;
- every 50 ms it sends authoritative time, beat, duration, playing state, song identity and time-aligned per-player scores back to Dynamic Overlay. Song progress, score, accuracy and other text therefore use the same clock as the pictures.
The replacement is fail-open. A normal replay iframe stays active until the compositor reports that exact player. Rotated, scaled or translucent replay nodes currently keep their normal iframe; unrotated nodes can be freely moved and resized. Browser/OBS sources do not activate this native path.
Create an overlay
Set Overlay name, Default scene, Canvas width and Canvas height. Creation also creates the first scene document. Then choose coordinator defaults: score setting, referee equivalence, match management, stream notifications, timeouts and whether the coordinator panel starts unlocked.
Scenes and components
A scene is a complete render output. A component is a reusable document that may be instantiated in a scene or another component. An overlay must retain at least one scene. Names produce link IDs/slugs and must be unique within their document kind. Scenes/components can be renamed, resized, reordered, exported and imported.
Changing the active scene updates legacy/active-overlay consumers; direct scene URLs continue to identify their requested scene. Prefer direct scene URLs for stable OBS sources.
Live state and mutations
The editor and renderer receive document creation/update/deletion, node creation/update/deletion and active-scene events. The editor queues/coalesces changes and sends bulk updates where appropriate. A viewer should recover from a refresh by loading the complete overlay tree and current match state, then resubscribing.
Security
Render URLs may carry or derive bearer authentication depending on the launch path. Treat copied private links as credentials. The Electron app mirrors the authenticated session into an isolated partition so access tokens do not need to remain in scene URLs. Never export secrets in public properties or node props.