Generative Visual Player
User Manual
Version 1.0.0 · Draft · macOS & Windows

Lumen is a generative visual player and VJ engine for macOS and Windows. It renders real-time WebGL2 shader scenes, reacts to live audio, and can be driven by DMX/Art-Net and OSC from a lighting desk or show-control system.

About this draft

This manual was generated directly from Lumen's source (index.html) rather than from hands-on use of the running app. Every parameter name, style name, OSC address, DMX channel mapping, and keyboard shortcut below is taken straight from the code. What it can't yet capture is the feel of using the app. Sections that couldn't be confirmed from the code are marked "to be documented" rather than guessed at. This needs a pass from someone who has actually run a show with it before it's finished.

1 · Introduction

Lumen is a generative visual player and VJ engine for macOS and Windows. It renders real-time WebGL2 shader scenes, reacts to live audio, and can be driven by DMX/Art-Net and OSC from a lighting desk or show-control system — making it usable both as a standalone visual instrument and as one more fixture in a larger lighting/AV rig.

The engine pipeline is: a generative scene shader (one of 19 selectable visual styles) renders into an offscreen buffer, which then passes through a feedback/FX post-processing chain (chromatic aberration, feedback trails, kaleidoscope, bloom, posterize), and the result is drawn to the main window and, optionally, a second output window for a projector or screen.

Lumen ships as a single self-contained HTML/JS/WebGL2 file wrapped in a Tauri desktop shell. It runs entirely client-side — no server or internet connection is required for the visuals, audio analysis, or show file storage.

Who this is for

VJs, lighting designers, and production techs who want a generative visual source that can free-run on its own, sync to a loaded song, or be remote-controlled from a lighting console or OSC controller.

2 · The interface

The window is a fixed layout: a header bar, the main stage (canvas) on the left, a scrollable settings panel ("aside") on the right, and a footer with quick-reference shortcuts.

RegionWhat it does
HeaderThe Lumen wordmark, the timecode readout (shows FREE or EXT mode), and status pills for Audio, Bridge, and Output, plus a live FPS counter.
Stage (canvas)The live WebGL2 render. Overlaid with an audio meter, the current style name, a beat-flash indicator, and a DMX-out colour swatch. Buttons in the corner toggle the waveform view, fullscreen, and the second-screen output window.
Waveform stripAppears over the bottom of the stage once a song is loaded — shows the song's peak waveform, a time ruler, beat ticks, and amber draggable cue markers. Click empty space to seek; drag a cue marker to re-time it.
Settings panel (right)Nine collapsible sections (numbered 01–09 in the UI): Generative Style, Color/Palette, FX Rack/DSP, Modulation Matrix, Audio Input, Song & Beat Sync, Images/Stills, Fixture/DMX Channels, Timeline/Cues/Timecode, Scenes/Presets, and Hardware Bridge. Click any section header to collapse/expand it.
SplitterA drag handle between the stage and the settings panel — resizes the panel between roughly 300px and 760px wide.
FooterA quick shortcut legend (space/1-6/B/F) and a transient status message area that shows feedback after actions (e.g. "Bank A stored.").

3 · Scenes & styles

Lumen has 19 generative styles, each its own GLSL fragment shader driven by shared parameters rather than pre-rendered footage — nothing is a video loop. Every style reads the same set of inputs (structure/motion parameters, scale, hue/saturation, and live audio bands) and produces a different procedural pattern from them, which is what makes it "generative" rather than a clip player.

The 19 styles, in engine order (style index 0–18):

#StyleWhat it is
0Noise FieldDomain-warped fractal noise (fbm)
1PlasmaClassic layered sine-wave plasma
2TunnelRadial tunnel/zoom with ring bands
3SpectrumRadial bars driven by frequency bands
4TruchetRotating Truchet tile pattern
5ParticlesLayered twinkling point clusters
6Solid ColourFlat colour field pulsing with bass
7GradientVertical gradient with noise-perturbed edge
8RingsConcentric rings expanding from centre
9VoronoiAnimated Voronoi cell mosaic
10MosaicPulsing grid-cell mosaic
11WavesLayered horizontal sine waveforms
12SpiralRotating multi-arm spiral
13HexGlowing hexagonal grid
14StarfieldMulti-layer scrolling star field
15MetaballsOrganic blending metaball blobs
16InterferenceTwo interfering radial wave sources
17RainFalling streak/rain effect
18ImageA user-imported still image, warped/zoomed by the same controls (see §11)

Select a style by clicking its button in the Generative Style section, via the 1–9 number keys (styles 0–8 only — see §14 for the shortcut caveat), via a DMX fader on channel 1, or via OSC (/lumen/style). Each style is shaped further by three sliders in that same section:

All styles also read live audio band levels (sub, bass, mid, high) directly in their shader code, so most patterns visibly pulse or shift with the music even before the Modulation Matrix (§5) adds any explicit routing.

4 · The FX / post chain

After the scene shader renders, a second full-screen post-processing shader applies, in this order: chromatic aberration → feedback (blended with the scene) → bloom → posterize → master brightness. The controls live in the FX Rack / DSP section (03). All are 0–1 sliders bound directly to shader uniforms:

Control (label)Internal nameWhat it does
FeedbackwarpBlends the previous frame back into the current one (trails). At 0 the feedback loop is effectively muted; higher values increase trail persistence.
Fb ZoomfbzoomZooms the fed-back previous frame in or out each frame (0 = zoom out ~4%, 1 = zoom in ~4%, 0.5 = no zoom) — this is what produces the classic feedback "tunnel" effect when combined with Feedback.
Fb RotatefbrotRotates the fed-back frame slightly about centre each frame (0.5 = no rotation).
KaleidokaleidoKaleidoscope mirror segments, from 0 (off) up to 16 radial segments at 1.0.
ChromachromaChromatic aberration — offsets the red/blue channels outward from centre.
PosterizeposterizeColour quantisation/banding; 0 = off, 1 = heavy posterize (down to ~3 levels per channel).
BloombloomCheap 4-tap bloom of bright areas sampled from the previous frame.
SpeedspeedGlobal time-scale multiplier fed into every scene shader's internal clock (roughly 0.3×–2.5× depending on value).
Order matters

The post shader samples the scene with chromatic aberration and kaleidoscope applied together, blends in the zoomed/rotated previous frame for feedback, then bloom, then posterize, then multiplies by master brightness. Extreme Feedback + Fb Zoom combinations can wash the image toward white/black quickly — moderate settings are more stable for long-running visuals.

5 · Audio reactivity

Enable audio input from the Audio Input section (05) — Lumen requests microphone/line input via getUserMedia and analyses it with the Web Audio API's AnalyserNode (FFT size 2048). Four band levels are computed each frame and displayed as live meters:

BandFrequency range (FFT bins)
Subbins 1–6
Bassbins 6–24
Midbins 24–140
Highbins 140–500

These four bands (audio.sub, .bass, .mid, .high) feed directly into every scene shader as uniforms, so patterns respond to the music even with no explicit routing configured.

Beat detection

Beat detection runs purely on the bass band: a running average of bass energy is tracked, and a beat fires when instantaneous bass exceeds 1.35× that running average (and is above an absolute floor of 0.12), with a minimum 250ms gap between beats. Each detected beat:

Beat → style switching

The Song & Beat Sync section (05B) has a Beat-Sync toggle. When on, every N beats (adjustable 1–32, default 8) the active style advances — either Sequential (next style in order, wrapping) or Random (a random style different from the current one). This switch happens inside the beat detection callback, so it is driven by the same bass-energy beat detector described above, not by a separate rhythm engine.

6 · Timecode & transport

Lumen has one shared internal clock (transport.t) that every shader's time uniform derives from. Each frame, it is updated by one of two rules:

The Timeline / Cues / Timecode section (07) exposes transport controls:

Tempo

A BPM value (0–180, default 120) is tracked independently of the transport clock and used by the tc modulation source (a beat-phase 0–1 ramp) and by the Modulation Matrix. It can be set two ways, toggled via the Tempo Source button:

External timecode

When Art-Net timecode arrives via the bridge or native layer, Lumen switches the header readout to EXT mode and sets transport.t directly from the incoming hours/minutes/seconds/frames, overriding the free-run/song clock for as long as timecode keeps arriving.

7 · DMX & the Art-Net bridge

Lumen can be patched into a lighting rig as if it were one DMX fixture, and can also drive its own output colour back out over DMX (e.g. to sync a real fixture to what's on screen).

Connection

Two connection paths exist, both described in the header comment and the Hardware Bridge section (09) of the UI:

When neither native nor WebSocket bridge is active, Lumen runs in simulation — the on-screen DMX channel faders act as manual stand-ins for a real desk.

DMX in — fixture channel mapping

The whole engine presents as a single 9-channel fixture. Incoming DMX values 0–255 on channels 1–9 map to:

ChFunctionEffect
1STYLESelects one of the 19 generative styles (value divided into 19 bands)
2BRIGHTMaster brightness (master param)
3HUEBase hue
4SATSaturation
5SPEEDAnimation speed
6FEEDBKFeedback amount (warp)
7KALEIDKaleidoscope segments
8CHROMAChromatic aberration amount
9COLOURSnaps hue/saturation to one of the 16 palette swatches (like a colour wheel on a moving-head fixture) — see §9's palette swatch list

Channels 10–13 are read as four auxiliary values (dmxAux[0..3]) not tied to any fixed parameter — they're only usable as dmx1–dmx4 sources in the Modulation Matrix, so an operator can patch a spare desk fader to modulate any parameter of choice.

DMX out

Roughly 10 times per second, Lumen downsamples the rendered frame to a 16×16 thumbnail, reads it back, and averages it to a single RGB colour, shown in the "DMX OUT · screen→rig" swatch on the stage overlay. This colour is sent out via the native Rust command, the Electron bridge, or the WebSocket bridge (whichever is active) — intended for driving a real fixture to match the on-screen colour.

8 · OSC control

OSC messages arrive via the bridge (UDP 8000, relayed over the WebSocket) or the native layer, and are dispatched by address. The full address space, as documented directly in the source:

AddressArgsEffect
/lumen/styleintSelect style 0–18 (float 0–1 is also accepted and mapped proportionally)
/lumen/style/next—Next style (wraps)
/lumen/style/prev—Previous style (wraps)
/lumen/param/<name>float 0–1Set a named parameter. Valid names: hue sat spread master scale speed paramA paramB warp fbzoom fbrot kaleido chroma posterize bloom
/lumen/colour (or /lumen/color)intPick palette swatch 0–15
/lumen/morphfloat 0–1Set A/B palette morph amount
/lumen/bpmfloatSet tempo (clamped 0–300)
/lumen/beatsyncint (0/1)Toggle beat→style switching
/lumen/play—Start transport (and resume song if loaded)
/lumen/stop—Stop transport (and pause song if playing)
/lumen/zero—Reset transport to 0 (and seek song to 0 if loaded)
/lumen/cue/next—Jump to next cue
/lumen/cue/prev—Jump to previous cue
/lumen/sceneintRecall quick bank slot A–F (0=A … 5=F)
/lumen/dmxch (1–13), val (0–255)Set a fixture channel exactly as if it arrived over DMX — channels 1–9 map per the table in §7; 10–13 set the aux modulation sources
Unknown addresses

Any address whose first segment isn't lumen, or whose second segment doesn't match a known section, is silently ignored.

9 · Cues, banks & scenes

Lumen has three layered levels of "save state," from most transient to most durable: cues (song-locked moments), quick banks (six manual slots), and named scenes (a saved library).

Cues

A cue captures the entire current look — style, colour, every FX parameter, the modulation matrix, and DMX channel values — tagged to a specific time. Add one with + CUE @ NOW in the Timeline section; CLEAR CUES removes them all. With a song loaded, cues render as amber draggable markers on the waveform, labelled with the style name they recall. As playback crosses a cue's time, its full state is recalled automatically. Cues can also be stepped with /lumen/cue/next / /lumen/cue/prev (see §8), which also seeks the song to the cue's time.

Quick banks (A–F)

Six one-key slots in the Scenes / Presets section. Tap a lettered button to recall it; shift-tap to store the current full state into it. Banks persist in the browser's localStorage between sessions (key lumen.bank.v1) and are also included in show export/import (§10).

Named scenes

An unlimited, named list of saved states. Type a name and click SAVE to add one; click a saved scene's name to recall it, OVR to overwrite it with the current state, or × to delete it. Scenes persist in localStorage (key lumen.scenes.v1) and travel with show export/import.

A/B palette morph is separate

The A/B Morph control in the Color/Palette section is a distinct, simpler mechanism: it stores two colour palettes (hue/saturation/spread/scheme) in memory as "A" and "B" and crossfades between them with a single slider — it is not persisted and is not part of a cue/bank/scene's state capture in the same sense (a saved scene does capture whatever hue/sat values were showing at save time, but not the A/B morph position itself).

10 · Show files

Everything that can be saved locally (banks, named scenes, cues, and the current tempo) can be exported to a single JSON file and re-imported — for backing up a show or moving it to another machine.

Export Show writes a file named lumen-show-YYYY-MM-DD.json containing:

{
  "app": "LUMEN",
  "v": 1,
  "bank": { "A": {...}, "B": {...}, ... },
  "scenes": [ { "name": "...", "state": {...} }, ... ],
  "cues": [ { "t": 12.3, "style": 4, "state": {...} }, ... ],
  "bpm": 120
}

Import Show reads a file in this shape and merges it in — bank slots and scenes are replaced wholesale, cues are replaced wholesale, and BPM is applied. Malformed files fail with a footer message rather than corrupting the current session.

Because storage is plain localStorage, Lumen works fully standalone as a single HTML file with no server — the only thing that requires a proper http:// origin (rather than opening the file directly) is microphone access for live audio input; loading a song file or working with already-saved banks/scenes does not need a server.

11 · Images / stills

The Images / Stills section lets you import a picture (any browser-supported image format) as a texture. Selecting the Image style (#18, see §3) displays it cover-fit to the stage, and the same Param A / Param B / Scale controls that shape the generative styles instead control image-specific behaviour: Param A drives a warp/displacement amount, Param B drives a palette-based hue-shift overlay, and Scale drives a zoom/pulse. The image responds to bass energy (subtle zoom pulse) exactly like the generative styles do, and passes through the same FX chain (feedback, kaleidoscope, chromatic aberration, posterize, bloom). CLEAR removes the loaded image.

12 · Output & second screen

The main stage canvas is always live in the primary window. OPEN OUTPUT ↗ captures the canvas as a media stream (canvas.captureStream(60)) and opens it in a separate borderless popup window showing just the video feed — intended to be dragged onto a second monitor or projector output and set fullscreen. FULLSCREEN instead fullscreens the main canvas in place. Because the output window is a live stream of the same canvas, both windows always show the identical frame — there is no independent "confidence view" vs "programme output" split; to be documented further if the live app behaves differently from what the code implies.

13 · Native bridge & platforms

Lumen ships as a Tauri v2 desktop application (package com.lumen.visualplayer, version 1.0.0) targeting macOS and Windows, built from this same single HTML file bundled as the frontend. Key facts from the build configuration:

On the web/browser side (running index.html directly, outside Tauri), Lumen degrades gracefully to the WebSocket bridge + getUserMedia microphone path described in §7.

14 · Keyboard shortcuts

KeyAction
SpaceToggle transport play/stop
1–9Select generative style 1–9 (styles at index 0–8 of the 19 available — there is no shortcut for styles 10–19; the footer legend in the app itself only advertises "1–6")
BTap tempo (same as clicking TAP)
FFullscreen the stage canvas

Shortcuts are ignored while focus is inside a text input or dropdown, so typing a scene name or adjusting a select won't accidentally trigger them.

15 · Glossary

TermMeaning
StyleOne of Lumen's 19 generative shader scenes (Noise Field, Plasma, Tunnel, …, Image). Selected by index 0–18.
FX / post chainThe second shader pass applied after the scene renders: chromatic aberration, feedback, kaleidoscope, bloom, posterize, master brightness.
FeedbackBlending the previous rendered frame (zoomed/rotated) back into the current one to create motion trails.
Modulation MatrixA patch-bay of source → destination routings that sum onto a base parameter value — e.g. routing the bass band onto the scale parameter.
CueA full saved look tagged to a specific time; recalled automatically as the playhead passes it, shown as an amber marker on the waveform.
BankOne of six (A–F) quick-recall state slots, stored locally and included in show export.
SceneA named, saved full state, distinct from banks — an open-ended list rather than six fixed slots.
Art-NetA protocol for carrying DMX lighting data (and, here, timecode) over a network, used by Lumen's bridge to receive DMX/timecode from a lighting desk and send DMX colour data back out.
DMXThe lighting-industry protocol for addressing up to 512 channels per universe; Lumen exposes itself as a 9-channel fixture (plus 4 auxiliary channels) on channels 1–13.
OSCOpen Sound Control — a UDP-based control protocol Lumen listens to (via the bridge, on port 8000) for remote parameter, transport, and cue control; see §8 for the full address space.
TimecodeThe running HH:MM:SS:FF clock shown in the header. Either free-running/song-following internally (FREE) or driven by incoming Art-Net timecode (EXT).
Beat envelopeA value that jumps to 1 on each detected beat and decays exponentially, usable as a Modulation Matrix source (beat).

LUMEN User Manual · Version 1.0.0 (Draft). This manual was generated by reading the app's source code, not by using the shipping app — expect a human editing pass for workflow and UX detail.