Performance mode: hiding the node graph from VJs
VidViz's node editor is honest about what the app is: boxes, wires, an executor. But hand it to someone who just wants to play visuals at a party tonight and you can watch the enthusiasm die grid square by grid square. This week shipped Performance mode — a live-mixing UI for beginner VJs that contains no visible nodes at all, built entirely out of nodes.
The lie that compiles
Performance mode looks like the tools VJs already know: four layers, a clip library on the left, a big preview, an A/B crossfader, FX slots per layer, a master strip. Click a clip — a video file or one of ~47 curated generators — and it plays on the selected layer. Familiar, boring, correct.
Underneath, there is no second engine. The mode auto-builds a node
graph: each layer's source node feeds effect chains, layers 1+2
composite into one stack, layers 3+4 into another, the two stacks meet in
a mix node — that mix input is the crossfader — then master opacity,
then output. Solo and mute compute down to effective opacities. If a
generator is audio-reactive, the builder notices its rms/beat inputs
and wires in a shared audio-analysis chain, tearing it back out when no
loaded clip needs it.
The same engine, executor, culling, and adaptive quality from the editor run unchanged. Performance mode is a view, not a fork — one UI writes graphs with a keyboard, the other writes them with a crossfader. Every hour spent on the engine keeps paying in both places, and there is no second implementation to drift.
Surgical edits, because the show is live
The constraint that shaped the internals: the frame must not hiccup. In the editor, rebuilding the graph on a structural change is fine — you are editing, a stutter is a shrug. Mid-set, a stutter is the audience noticing. So performance mode's operations are deliberately surgical:
- Loading a clip rebuilds only that layer's nodes, splicing them in while the other three layers keep rendering undisturbed.
- Toggling an FX doesn't add or remove anything — effects are always wired in series and the toggle flips the node's bypass flag. Zero allocation, zero topology change, zero glitch.
- Adding or removing an effect creates or deletes exactly one node and rewires two edges around it.
The pattern generalises: a live system wants its cheap operations to be provably cheap — flag flips and single-node splices — with anything expensive pushed to moments the operator chooses.
Presets, and the fidelity bug
Preset scenes — whole desk states saved and recalled — surfaced a subtle
bug worth recording. Presets store only the parameters the user touched.
But some node types have trigger parameters that imply siblings: choose
the "Terrain Flyover" model and a handful of dependent settings should
follow. Restoring a sparse preset set the trigger without the
implications, and scenes came back subtly wrong — right nodes, wrong
mood. The fix moved implied-parameter application into the graph store's
addNode itself, so every creation path — editor palette, preset
restore, auto-builder — resolves a node's implications identically,
without overriding anything explicitly set. Sparse serialisation is a
contract: whoever rehydrates must apply the same defaults logic as the
original author. Centralise it or drift.
Sharing the stage
Two more pieces round out the live story. The second screen button enumerates displays and opens a borderless output on whichever one the projector is, with a resolution ladder (480p–4K) right in the toolbar — the polite-degradation story from the perf work, now a knob a VJ can just turn when the venue laptop wheezes. And rather than growing its own transport, performance mode mounts the same sequencer panel from the editor in a variant trim — its toolbar swapping graph-editor toggles for fullscreen, second-screen, resolution, and MIDI-learn buttons. MIDI mapping covers the things hands actually reach for mid-set: layer opacities, the crossfader, master, transport.
Both modes stay mounted, sharing one WebGL canvas that physically re-parents between them — display toggling, not remounting, so switching views mid-playback doesn't restart anything.
Who it's for, and what got hidden
The design bet is in the curation. The node registry has 200+ types; the clip library shows ~47 generators and ~60 effects, hand-picked and human-labelled, in categories a newcomer can browse. Right-clicking an FX opens the same parameter controls the editor uses — the depth is all still there — but nothing about the default view demands you understand what a Unit port is. Progressive disclosure, with the node editor one toggle away as the "view source" of your live set.
The part I'd defend hardest is what performance mode isn't: it isn't a separate product bolted alongside the editor. It's a compiler from a simple mental model (layers, clips, a crossfader) to a rich one (the graph) — and like any good compiler, its output is inspectable. The beginner-to-expert path is a toggle, not a repurchase.