vizz documentation GitHub

vizz documentation

A realtime generative visual instrument. This covers building a look, playing a set, and wiring it into a rig — from first launch to a projector at a venue.

Install and first launch

macOS — download from the latest release and drag vizz.app to Applications, or run:

curl -fsSL https://raw.githubusercontent.com/legofsalmon/vizz/main/scripts/install.sh | bash

Releases are signed with a Developer ID and notarized, so they open with a normal double-click. Syphon is embedded — there is nothing else to install.

Windows and Linux build from source and are tested in CI, but have no installer yet. You will need a Rust toolchain:

git clone https://github.com/legofsalmon/vizz
cd vizz
cargo run --release

What happens on first launch. A window opens at 1280×720 showing a slowly turning sphere of particles, with the control panel on the left. OSC is listening on UDP 7000 and — on macOS — a Syphon source named vizz is already published, so Resolume or VDMX can see the output before you have touched anything.

The three screens

vizz has one window and three overlays on it. The visuals keep running underneath all of them.

ScreenKeyWhat it is for
Control panelTab Every parameter, grouped. Where you build a look. Open on first launch.
PerformanceP Big faders, scene pads, punch buttons. Where you play. Nothing here can destroy work.
Modulation canvasG A node graph: what moves what. Editing, not performing.

Press ? at any time for the shortcut list on screen.

The vizz control panel: status line, collapsible sections, preset list and grouped parameter sliders.
The control panel. The status line at the top stays visible; everything above the presets folds away, because it is setup rather than performance.

Shows

The name at the start of the panel, and at the start of the performance strip, is the show you have open. Click it for the list of shows on this machine, and for new show…, save as…, rename… and delete.

A show is everything you built for one band or one night: both grids, the pages of pads, your looks, your patches, your fader layout and your slider ranges. Switching shows swaps all of it at once.

A show carries its own preset library, which is what makes one a complete thing you can copy to another machine and have work — a pad names a look, so the pool it names travels with it. So new show… starts with an empty library: the built-in looks are always there, save as… is how you carry your own looks into a new show, and the built-in set is one right-click away on the + beside the deck chips.

What does not travel is the rig. Your output size, audio device and controller map stay where they are, because they describe the machine in front of you rather than the set you are playing — plug into a different rig and your show is unchanged; open a different show and your rig is unchanged.

There is no save button. Everything above is written the moment it changes, so save as… means copy this show and carry on in the copy rather than "write it down before you lose it". Nothing is ever lost for not having pressed anything.

A name already taken counts up rather than overwriting: type Warehouse twice and the second one is Warehouse 2. The last show cannot be deleted — there would be nowhere for the next pad to live.

Build your first look

The fastest route in is to start from something that already looks like something, then pull it apart.

  1. Click a preset. In the panel's Presets list, click Butterfly (the Lorenz attractor) or Tunnel (feedback, the high-energy one). The look glides in over a few hundred milliseconds rather than cutting.
  2. Open a parameter group. The list below is grouped by address — particles, shape, fx, color, camera. Each header shows how many controls it holds.
  3. Move something obvious. /fx/trail is the one that turns a particle field into VJ material: it is how much of the last frame survives into this one. Take it to 0.9 and add /fx/zoom for a tunnel.
  4. Find a control by name. Press / and type. The groups flatten while you filter, because once you have typed a name you already know what you want.
  5. Keep it. Type a name in the box under the preset list and press Enter. Your presets live beside the built-ins and can be recalled by number, MIDI or OSC.

Sliders that will not stay put. A parameter with a ~ beside it is being modulated — the value is still yours, and modulation rides on top as an offset. Hover the mark to see the current offset. The >< button narrows a slider's working range so a fader can sweep the part you care about.

Presets

A preset is where every knob is sitting. It is not the modulation graph — that is a patch, stored separately, so recalling a look never rewires your LFOs.

Six ship with the app and cannot be overwritten: Slow bloom (a neutral opener), Butterfly, Tunnel, Stage (cloud inside the room, forced perspective), Confetti and Ribbon. Your own go beside them.

Slot 0 means nothing selected and presets start at 1, so a controller resting at zero cannot fire anything on startup. Recall is edge-triggered: it fires when the slot changes, so a button parked on a slot does not re-apply its preset every frame and pin the controls you are trying to adjust.

Scenes and transitions

A preset recalled by number is a cut. A scene is the other thing you want during a set: moving from one look to the next over musical time.

Sixteen pads, laid out like a sequencer — four by four in the panel, sixteen across on the performance layout.

  1. Build a look.
  2. Click store to arm it, then press a pad. The pad now holds that look.
  3. Repeat for as many pads as you want to travel between.
  4. Press pads to move. Set blend to the transition length in seconds and pick a curve — linear, smooth, ease in, ease out, or cut.

The blend is in the data, not in the picture. Crossfading two rendered images of a particle field gives a double image that reads as a mistake. Interpolating the parameters gives one field whose settings are somewhere between the two — still one of everything, and it looks like the material moving rather than like a mixer.

Two things do not interpolate. Switches jump at the half-way point: /fx/mirror has off, x and quad and nothing sensible between them. Cloud slots never blend, because half way between slot 0 and slot 2 is slot 1 — a different cloud entirely, which would flash on screen part-way through every move.

Firing during a transition re-aims from wherever the blend has reached, so you are never locked out until the last move finishes.

Autopilot walks the filled pads in time with the beat clock, every /scene/bars bars. It fires on the bar boundary and never on the frame you switch it on. The performance layout shows it as a wide green bar naming the pad it is heading for.

Decks and Resolume

Sixteen scenes and sixteen gravity slots is a generous evening if the set is one continuous thing, and nowhere near enough if it is twelve songs that each want their own looks. A deck is a page of both grids together, one per song.

The chips above the pads on the performance layout are the set list.

  1. Click a chip to turn the page. The pads underneath — scenes and gravity both — become that song's.
  2. + makes a fresh empty page; right-click a chip and choose duplicate to start the next song from this one, which is usually what you want.
  3. Right-click for rename… and delete page. The last page cannot be deleted.

A deck holds references, not copies. Looks live in one pool, so the same preset can sit on a pad in every song and refining it once improves all twelve. Deleting a page throws away an arrangement, not an evening's work.

Turning a page changes nothing on screen. Switching decks fires nothing and writes no parameter: whatever is showing stays until you press a pad. Every page turn happens in front of an audience. A blend already running finishes, but stops claiming a pad — after a page turn no pad on screen produced what you are looking at.

/deck/select is an ordinary parameter, so a chip, a controller button and an OSC message are one gesture. Bindings name the deck number, exactly as the pads and preset slots do, so sixteen buttons address sixteen pages. Right-click a chip to learn one.

Following Resolume's columns

Arena's column launches can drive vizz. In Arena ▸ Preferences ▸ OSC turn on OSC Output and point it at this machine on vizz's OSC port (7000 unless --osc-port says otherwise), then turn on resolume beside the deck chips.

Launching Arena column N then fires column N here — the scene pad and the gravity pad of that number, together, which is what a column means in Arena too. Keep the two grids arranged in parallel and one button runs the video and the field.

Off unless you ask for it. The OSC listener binds every interface by default, so following hands anyone on the venue's wifi the scene transport. The switch is remembered between runs.

Each page declares which columns it follows. A deck's origin is the Arena column its column 1 follows, on the chip's right-click menu. With one grid in Arena, leave every page at 1. With one long composition and a song every sixteen columns, set 1, 17, 33 … and each page follows its own stretch; a column outside the live page's stretch does nothing rather than landing on the nearest pad.

Relaunching the column already showing fires it again, unlike pressing the same pad twice — a relaunch in Arena is a deliberate re-trigger and has to land. /column/fire is an ordinary address, so anything else that speaks OSC can play the show by column too.

Arena's deck changes come too. /composition/decks/N/select picks page N here. A deck is the song and a column is the section, so with the same messages reaching the lighting rig one launch moves the video, the lights and the field to the same place.

The built-in set

A machine that has never had a show set up on it opens with one: twenty songs, eight sections each, in the same idiom the app was built alongside — hard-edged flat geometry, black paper, bold limited palettes, layers at close frequencies interfering into moiré.

The pads are the parts of a song, in the order you play them: Intro, Build, Break, Drop, Bridge, Peak, Outro, Blackout — the same eight the lighting rig uses.

Only on a machine with no show on it. No deck file, one page, nothing on it. Anything else and the set stays out of the way. To ask for it later, right-click the + beside the deck chips; it replaces every page, so it asks once.

Each song carries one designed look, and its eight pads are that look read through the shape a song has — a bed, a rise, something stripped back, a hit, a hold, the biggest thing in the song, a return to the bed, and an ember. The Drop pad is the designed look exactly; everything else is measured from it. A quiet song's peak stays under a loud song's, so the set's arc survives into the pads.

Every pad is an ordinary preset, so any of them is one store away from being yours.

Punch FX

The things you do on the drop. All five are momentary — they apply while held and rest at zero — so nothing can leave the output stuck inverted, and no preset or scene can capture one.

GestureAddressWhat it does
Flash/punch/flashWhite out. Space is the key.
Black/punch/blackBlackout — kills the colour, keeps the coverage.
Invert/punch/invertInverts the finished picture.
Freeze/punch/freezeHolds the picture. The set keeps moving underneath, so releasing snaps to where the music got to.
Strobe/punch/strobeBeat-synced. /punch/strobe_div sets beats per cycle.

On the performance layout they are the PUNCH row: press and hold, or shift-click to latch one on. A learned MIDI note is momentary for free, because the gesture rests at zero — press to fire, release to stop, with no mode to get stuck in.

Gravity

Four wells that pull or push the particles, sitting above whatever shape is on screen. Positive strength attracts, negative repels; radius sets the reach; /gravity/amount is the master depth for the whole layer.

Gravity has its own 16-pad grid, with its own store, blend time and curve, so a gravity move can be fired independently of a scene change — the field can lurch without the look changing, or both can move at once on different timings.

Performance faders

The CONTROLS row is fourteen assignable faders plus the master. Click a fader's caption to assign it to any parameter; click learn beneath it and move a controller to bind MIDI.

The vizz performance layout: status strip, punch row, scene grid, gravity grid, preset row and a row of faders.
The performance layout. Status, punch, scenes, gravity, presets and faders — read in a dark room at a glance, over a near-opaque scrim so a strobe cannot take the readouts with it.

The master is /master/dim, the panic fader. It is never captured by a preset or a scene, so nothing you fire can undo a blackout you reached for.

Shapes and geometry

/shape/mode sweeps through eight forms, and fractional values sit between two of them — it is a sweep, not a switch:

0 sphere · 1 torus · 2 knot · 3 grid · 4 shell · 5 Lorenz · 6 Aizawa · 7 cloud pair · 8 sphere again

The range wraps, so the top morphs the Aizawa attractor back into the sphere. /shape/morph adds an extra blend into the next form and /shape/twist shears the whole field.

Lorenz and Aizawa are real strange attractors, integrated per particle rather than drawn as a static curve — the field genuinely flows along the attractor, which is why they read as motion rather than as a picture of a shape.

Point clouds, words and images

Eight cloud slots: two built-in attractors and six loadable. Files, typed words, images and a live stream all compete for the six.

From a file

Drag a .ply, .xyz, .csv or .pts onto the window, or start with --cloud scan.ply. PLY reads both ASCII and binary little-endian, with per-point colour where the file has it. A file that will not parse is a warning, never a startup failure.

From a word

Open the panel's clouds section, type into the type a word field and press Enter. The string is rasterized with the app's own font into a cloud you can morph against any other slot. Typed clouds persist as text:WORD and come back after a restart.

From an image

Drag a .png or .jpg on. Position comes from the pixel grid, colour from the pixel, and a shallow relief from luminance. Fully transparent pixels are skipped, so a logo keeps its silhouette instead of arriving as a rectangle.

From a live stream

vizz --live-cloud tcp://192.168.1.9:9000    # connect to a streaming app
vizz --live-cloud listen://0.0.0.0:9000     # wait for one to connect here
vizz --live-cloud /tmp/live.ply             # re-read a file as it is rewritten

While it is listening, the panel prints the address to send to — send to 192.168.1.42:9848 — with a button to copy it. Point your sender at that. It is only shown for a listen:// address: if you are dialling out to host:port instead, the address that matters is the other machine's.

Showing and morphing them

A cloud you load is shown. Dropping a file, typing a word, naming one with --cloud, or the first frame of a live stream all select the new slot as /cloud/a and point /shape/mode at the cloud pair. The shape glides there rather than cutting, so the field turns into the cloud over about a second.

The one case that does not move the shape is the bank coming back at startup: the clouds you loaded in earlier sessions are restored to their slots, but the look you left behind is left alone.

/cloud/a and /cloud/b pick the two slots and /cloud/morph blends between them. Slot choice is stepped — half a slot is not a cloud — while the morph is swept and modulatable, so it can be driven from an LFO, the beat clock or an audio band.

Particles keep their index across the blend, so the same point travels from one cloud to the other rather than the field being re-scattered. A blend between two unrelated clouds passes through a shapeless middle: that is inherent to index-based morphing. Clouds with related structure morph far better than arbitrary pairs.

Clouds are centred and uniformly scaled into the same box the procedural shapes use, so /particles/spread means one thing everywhere. Fewer points than the slot holds means each is repeated with a small deterministic jitter, because a dense clump at the origin is far more visually wrong than slight duplication.

Live video as a point cloud

vizz --video-source test      # the built-in pattern
vizz --video-source "OBS"     # an NDI source, matched as a substring
vizz --list-ndi               # what is on the network

A video input arrives as a cloud in its own slot. That is the whole design: /cloud/a, /cloud/b and /cloud/morph select and blend it, the palette tints it, the spread scales it, and it morphs against a scan or an attractor with nothing else needing to know it is live. The first frame points the shape at it, the way a dropped file does.

Each particle takes a fixed cell of the picture and stays there, so the field reads as a cloud of the video rather than noise sampled from it. Position comes from the cell, colour from the pixel, and depth from whatever /video/relief names.

ControlWhat it does
/video/depthHow far the relief pushes along z. Signed, because a picture standing proud of the plane and one sunk into it are different looks; 0 is the flat picture, which is a look too.
/video/reliefWhat does the pushing: luminance, hue, saturation or chroma. Luminance is the honest default; the colour ones are what a flat, evenly lit source needs.
A video test pattern rendered as a particle cloud, its colour bars standing at different depths.
The built-in test pattern as a cloud: colour from the pixel, depth from luminance, seen from the default camera.

--video-source test is a diagnostic. "Nothing on screen" has two causes — the feed, or the wiring — and they need telling apart. The pattern is generated in-process and goes through the identical path, so a blank output with it running is a fault in vizz, and a blank output without it is the network or the sender. It moves on purpose: a still pattern proves a frame arrived once, a moving one proves frames are still arriving.

Vector layers

The print side of the app: four layers of hard-edged procedural pattern — rings, stripes, checker, polygon, star, rays, dots — in flat ink colours from a shared four-slot palette (/pal/0..3), composited with multiply/screen/difference-style blends. Two layers at near frequencies interfere into moiré. Edges are analytically antialiased and stay razor-sharp at any resolution.

Two ring fields multiplied into red and blue moiré interference.
The Interference preset: one recall from a cold start.

Start from a preset. Three vector looks ship after the six particle ones — Interference, Poster and Signal. Recall one and the print look arrives whole; the particle field steps aside via /particles/count 0, which is part of the look and comes back with the next particle preset.

The performance layout grows a LAYERS strip when any layer is on — hidden otherwise, like the gravity grid. Per layer: the ink swatch, the generator (click cycles, right-click back — off is on the wheel), the blend mode, and drags for opacity and frequency. Faders remain the way to ride a layer parameter under MIDI.

ControlWhat it does
/vec/placescene (default): behind the particles, inside the feedback chain — trails, punch and the tone-map apply, layering works. print: after the post chain — exact ink bytes, untouched by feedback, and deliberately out of reach of punch and particles.

A preset captures its placement. A /vec/place override sent in the same burst as a recall loses to the preset — send it after the recall lands.

The "Pulse" patch ships in the modulation canvas's load menu: the kick band gates a snap envelope that blinks layer 2 out on each hit, and a four-beat phasor drifts layer 1's phase. Load it over any vector preset and the layers move with the music.

Six vector looks: ring moiré, stripe difference, checker and star, dots and rays, kaleidoscope, grey multiply test.
The renderer's contact sheet: every generator, the kaleido fold, and five blend modes.

Camera moves

A camera move is the one gesture you cannot make by hand: orbiting smoothly for eight bars while also firing pads is two jobs and one pair of hands. /camera/move picks one of ten canned paths, move_bars sets how long a cycle takes, and move_size how far it travels.

MoveWhat it is for
orbitA full turn per cycle. The one that can run all night.
swayHandheld: a partial turn back and forth, the horizon breathing under it.
pushIn and back out — the build.
pullOut and back in — the reveal.
craneRising over the top, looking down by the end.
spiralA helix: turn, rise and close all together. The drop.
look aroundThe camera holds still and its aim sweeps — standing in one place and turning your head.
fly throughIn through the front, out the back, and round again.
walkthroughFour legs and four corners of a square, at eye level, inside the cloud. Moving through a house.
driftVery slow, never repeating inside a song, always moving. For long ambient sections.

A move is added to the camera your faders already describe, never written back into it. Switch one off and you are exactly where you were, and a move running is never a reason you cannot still steer. Rate is in bars, so a move locks to the same clock as the sequencer and the LFOs.

/camera/at_x, at_y and at_z aim the camera at a point in the world — which is what makes a walkthrough possible. Pan moves the target in the camera's own screen plane, so it keeps the subject centred by construction: right for framing, and no use for travelling.

Light

Two movable lamps and a directional sun, on top of an ambient level. Everything defaults to off, and off means identical — ambient is 1 and every lamp is 0, which multiplies the picture by exactly one, so no preset you have ever saved looks any different.

Lamps light a volume. Each has a position, a reach, a level and a colour, and falls off smoothly with distance. Walk one through a scan and it reveals the scan. This works on everything — imported clouds, procedural shapes, live video — because it only needs to know where a point is.

The sun lights surfaces. A wall facing the light comes up, a wall facing away goes down. That needs to know which way each point faces, so it only does anything on a cloud that has normals — see below. /light/shape is the dial between the two readings: at 0 a lamp is pure volumetric falloff, at 1 it respects the surface.

Lamps are white until you colour them. Each has a hue and a tint, because hue on its own has no value that means "no colour" — hue 0 is red, so a lamp described by hue alone would turn your scan red the moment you raised it to see what it did.

/light/torch puts lamp 1 on the camera. It is the partner to a walkthrough: light arriving from where you are is what makes moving through a scan read as moving, rather than as the scan fading up.

Normals

A point cloud is points. Whether it also knows which way its surface faces depends on whoever exported it, and most exports leave the field empty. vizz reads nx/ny/nz from a PLY when they are there, and works them out from each point's neighbours when they are not — about a tenth of a second when a cloud loads. A cloud that genuinely has no surface — a procedural shape, a video frame — is left alone, and the sun simply does nothing to it rather than lighting it from a direction nobody measured.

Shading is two-sided: a surface always faces you. Fitting a plane to neighbours cannot tell a normal from its opposite, and picking consistently across a whole cloud still comes out backwards for a scan of a room, where the surfaces you want lit face inwards. There are no shadows here for two-sidedness to contradict, and the alternative is half your scan going black for a reason you cannot diagnose from the front of a stage.

Colour and palettes

/color/palette starts at 0 = plain HSV and crossfades up through four cosine gradients — warm, ember, ice, neon — with your own loaded palettes from 5 up. /color/spread is how much of the gradient the field spans; /color/drive picks what chooses each particle's colour:

0 index · 1 radius · 2 depth · 3 height

Driving by depth is what makes a cloud read as three-dimensional on a flat screen. Driving by index keeps a scan's own colours coherent.

Your own palettes: drop a palette file on the window and it loads into the next slot and selects itself. Re-dropping an edited file reloads it in place, so you can iterate in a text editor with the app running. Imported cloud colour multiplies the palette rather than replacing it, so the palette still works as a tint and an uncoloured cloud is unaffected.

Effects

The output chain, in order: feedback, mirror, glow, RGB shift.

ControlWhat it does
/fx/trailFeedback — how much of the last frame survives. The single most useful control in the app. Capped below 1.0, because at 1.0 nothing decays and the frame saturates to white within seconds.
/fx/zoomPer-frame zoom of the feedback. With trail up, this is a tunnel.
/fx/spinPer-frame rotation of the feedback. With zoom, a vortex.
/fx/mirrorOff, mirror, quad, kaleido. A switch, not a sweep.
/fx/glowBloom lift.
/fx/shiftRadial RGB split — chromatic aberration.

Camera and room

A real camera looks into the field: /camera/distance, /camera/orbit, /camera/elevation, /camera/fov, and /camera/pan_x / /camera/pan_y to slide the view off-centre. /camera/focus and /camera/defocus give real depth of field — with defocus up, near and far particles bloom into soft discs and the field gains depth a flat render cannot fake.

The room

An optional wireframe room sized to the frame, for forced perspective and parallax. Raise /room/brightness to see it. /room/depth sets how far back it goes, /room/converge how hard the grid converges, and /room/vanish_x / /room/vanish_y move the vanishing point — which is how you match the room to where the audience actually sits relative to the screen.

/room/anchor places the cloud between the front and back of the room, and /room/embed bends the cloud's own perspective toward the room's, so the particles sit in the space rather than floating in front of a drawing of one. The built-in Stage preset is this set up and ready.

Audio reactivity

vizz analyses an audio input into four bands plus a broadband level, and those are available as modulation sources.

  1. Open the panel's audio section and pick an input from the device list. (Or start with --audio-device "Scarlett" — it matches on a substring; --list-audio prints the names.)
  2. Play something typical of your set — not a quiet intro.
  3. Press fit. Every band's gain is scaled from the last few seconds of what actually arrived.
  4. Check the meters. Each band shows two stacked bars: what modulation receives on top, what is arriving underneath. A red mark on the right means the band is pinned and the gain is too high.

Each band has editable low and high edges in Hz and a gain in dB. The defaults are low / lo-mid / hi-mid / high, but a kick-only band of 40–90 Hz driving size is often more musical than a broad one.

There is no correct default gain. It depends on the interface, the track and how hard it is being driven. fit is the honest answer — it reads your actual signal instead of guessing.

Tempo and the beat clock

One beat clock drives the strobe, scene autopilot, phasors and beat triggers. It can get its tempo three ways:

Tap and auto always win control back, so a stale clock source can never lock you out mid-set.

The modulation graph

Press G. Nodes on a canvas: sources on the left, operators in the middle, parameter sinks on the right. Drag from an output to an input to wire them.

Sources

LFOFree-running or beat-locked, several shapes.
BandOne of the four audio band envelopes, 0–1.
LevelBroadband level.
PhasorA ramp 0–1 over N beats, locked to the beat clock, so the whole patch can phase off one saw.
Beat triggerA pulse on each beat division boundary. Every trigger of the same division fires together.
ConstantA fixed value — useful as an offset or a manual depth.

Operators

CurveBend a linear signal into something with shape.
MathTwo inputs: add, multiply, min, max…
ScaleAffine — the workhorse for turning a unipolar source bipolar (multiply 2, add −1) or trimming a range.
SmoothAsymmetric attack/release slew. Tames anything twitchy.
QuantiseSnap to N steps — turns a smooth sweep into something that lands.
Sample & holdLatch a value when a trigger rises.
Gate1 above a threshold, 0 below, with hysteresis so a band hovering at the line does not chatter.
EnvelopeAttack/decay fired by a rising edge. Retriggering climbs from the current level instead of clicking to zero.

A worked patch: kick in, size punches out

  1. Add a Band node set to band 1 (the low band).
  2. Add a Gate and wire the band into it. Raise the threshold until it only opens on the kick.
  3. Add an Envelope — short attack, decay to taste — and wire the gate into its trigger.
  4. Add a Param sink addressed to /particles/size and wire the envelope in. Set depth for how far it moves.

Swap the Band for a Beat trigger and the same chain is tempo-locked instead of audio-driven, with nothing else rewired.

Patches are saved separately from presets. The canvas remembers its pan, zoom and patch name across launches. A wire that would make a loop is refused with a reason, and a Param node aimed at nothing says missing rather than failing silently.

MIDI

Controllers connect automatically — plug one in and it appears in the panel's midi section. Nothing needs configuring first.

Learning a control

  1. Go to the performance layout (P).
  2. Click learn under the fader you want, or on a scene pad, or on a preset button.
  3. Move the knob or press the pad. The binding appears as a chip (ch1 cc21) under the control.

While learning, the panel echoes whatever is arriving — so a controller that is not sending at all is immediately distinguishable from a mapping problem. Bindings are saved as you make them and survive a restart.

Notes are momentary, CCs are absolute. A learned note on a punch gesture fires while held and releases when you let go, because the gesture rests at zero. A CC on a fader takes the fader's full range.

MIDI clock

If the device sends clock, vizz can follow it — see Tempo. Clock traffic can never be captured by a learn: an armed learn ignores clock messages, so arming a learn while a mixer is running does not immediately bind to the clock.

OSC

Send standard OSC to UDP 7000 (change it with --osc-port). Float, int, double and bool arguments are all accepted. Unknown addresses and malformed packets are logged and ignored — control input can never crash the renderer.

# TouchOSC, Max, Pd, a Python script — anything that speaks OSC
/fx/trail 0.92
/shape/mode 5
/preset/recall 3

Every parameter in the app is an OSC address, and every address in the table below is a parameter — the panel is generated from the same table, so the two can never drift apart. The full list is below.

Two families of addresses are listened for without being parameters: /composition/columns/N/connect and /composition/decks/N/select, which are what Resolume Arena emits when a column is launched and when a deck is chosen. They are translated into /column/fire and /deck/select on the way in, and only while following is on.

Keyboard

19, 0Fire preset slot 1–10
SpaceFlash — white out while held
TabShow or hide the control panel
PPerformance layout
GModulation canvas
/Filter the parameter list
?The shortcut list, on screen
F11Fullscreen on the window's monitor
EscLeave fullscreen; otherwise quit (asks once)

Esc asks before quitting because it is one key, next to nothing, on a machine whose whole job is not going black. A second press within a few seconds confirms.

Syphon, NDI and output sizes

Syphon (macOS)

On by default. vizz publishes a source named vizz that appears in Resolume, VDMX, MadMapper and TouchDesigner with no configuration. It is zero-copy — the texture is shared on the GPU, never read back — so it costs almost nothing. Disable with --no-syphon; rename with --syphon-name.

NDI (all platforms)

vizz --ndi                  # publish as "vizz"
vizz --ndi --ndi-name Deck1 # or under your own name

NDI needs the runtime installed on the machine; vizz loads it at runtime and says so clearly if it is missing. Frames are read back asynchronously through a ring, so a slow network drops frames on the NDI output and never stalls the renderer.

Render size and output size

In the panel's outputs section: set the output size (720p / 1080p / 1440p / 4K presets, or type one), and a render multiplier from 0.5× to 2×. Rendering below output size is the cheapest way to hold frame rate on a laptop; above it is supersampling.

16-bit float master gives the feedback chain headroom before it clips — worth it when trails and glow are heavy. It doubles the master texture's memory and is off by default.

Recording

vizz records the master output as a PNG sequence. Every finished frame is a finished file, so a crash mid-take costs nothing already written.

  1. Press the REC chip on the performance layout's status strip. (The panel's outputs section has the same control, if that is where you already are.)
  2. The chip turns red and counts elapsed time, frames written and frames dropped.
  3. Press it again to stop. A notice names the folder.

Takes land in ~/Movies/vizz/vizz-<timestamp>/ on macOS and ~/Videos/vizz/… elsewhere. Assemble one with ffmpeg:

ffmpeg -r 60 -i frame_%06d.png -pix_fmt yuv420p take.mp4

Alongside the frames is a frames.csv of per-frame wall-clock times, so a take that dropped frames can be assembled honestly instead of silently running fast.

Recording never stalls the show. A slow disk drops frames on the recording only, and the drops are counted on the chip rather than hidden. A full disk stops the take with a notice instead of retrying sixty times a second. Expect drops at 1080p60 — PNG encoding is at the edge of one core — and lower the output size if the count climbs.

/record/active is an ordinary parameter, so OSC and a learned MIDI button can start and stop a take too.

Fullscreen and venue setup

F11 fills the monitor the window is on — drag the window to the projector first, then press it. The first Esc leaves fullscreen.

vizz --fullscreen              # start fullscreen
vizz --fullscreen --monitor 1  # on a specific monitor

The last F11 choice is remembered between launches, so a machine that always runs fullscreen does not need telling twice.

A venue checklist

Every OSC address

Every parameter, with its range and default. This table is checked against the running app by a test, so it cannot drift out of date.

AddressRangeDefaultMeaning
/particles/count0 – 50000060000live particle count
/particles/size0.001 – 0.20.015sprite size
/particles/speed0 – 40.6motion rate (phase-continuous)
/particles/spread0.05 – 31.2field radius
/particles/hue0 – 10.58base hue
/particles/saturation0 – 10.8color saturation
/particles/brightness0 – 21value multiplier
/shape/mode0 – 80geometry; fractional values morph: sphere · torus · knot · grid · shell · Lorenz · Aizawa · cloud pair · sphere again
/shape/morph0 – 10extra blend into the next form
/shape/twist0 – 20shear and vertical twist
/fx/trail0 – 0.980feedback: how much of last frame survives
/fx/zoom0.9 – 1.11per-frame zoom of the feedback (tunnels)
/fx/spin-0.1 – 0.10per-frame rotation of the feedback
/fx/mirror0 – 300 off · 1 mirror · 2 quad · 3 kaleido
/fx/glow0 – 10.25bloom lift
/fx/shift0 – 10radial RGB split (chromatic aberration)
/punch/flash0 – 10white-out while held — Space, a punch button, or a learned MIDI note
/punch/black0 – 10blackout while held; rgb only, coverage stays
/punch/invert0 – 10invert the finished picture while held
/punch/freeze0 – 10hold the picture; the set keeps moving underneath
/punch/strobe0 – 10beat-synced strobe while held
/punch/strobe_div0.25 – 40.5beats per strobe cycle
/color/palette0 – 150palette row: 0 hsv · 1 warm · 2 ember · 3 ice · 4 neon · 5+ loaded palettes
/color/spread0 – 10.12how much of the palette the field spans
/color/drive0 – 30what picks the colour: 0 index · 1 radius · 2 depth · 3 height
/cloud/a0 – 80first slot of the cloud morph pair
/cloud/b0 – 81second slot of the cloud morph pair
/cloud/morph0 – 10blend position between the pair
/video/depth-2 – 20.6how far the picture's relief pushes along z; 0 is flat
/video/relief0 – 30what pushes it: 0 luminance · 1 hue · 2 saturation · 3 chroma
/lN/kind (N = 1–4)0 – 70layer generator: off · rings · stripes · checker · polygon · star · rays · dots
/lN/freq (N = 1–4)0.5 – 648pattern frequency
/lN/phase (N = 1–4)0 – 10pattern phase offset; unsmoothed, so steps snap
/lN/drift (N = 1–4)-2 – 20.1how fast the pattern walks on its own, turns/sec of visual time; 0 is still, negative reverses
/lN/duty (N = 1–4)0.05 – 0.950.5ink/paper ratio within a period
/lN/sides (N = 1–4)2 – 164polygon/star sides; a sweep, fractional counts morph
/lN/inset (N = 1–4)0 – 10.5star valley depth
/lN/fold (N = 1–4)0 – 120kaleidoscope wedges; below 2 is off
/lN/invert (N = 1–4)0 – 100 fill · 1 invert
/lN/x (N = 1–4)-2 – 20layer centre, sideways
/lN/y (N = 1–4)-2 – 20layer centre, vertical
/lN/rot (N = 1–4)-2 – 20layer rotation, turns
/lN/scale (N = 1–4)0.05 – 81layer scale
/lN/color (N = 1–4)0 – 30which ink the layer prints with
/lN/blend (N = 1–4)0 – 60normal · multiply · screen · add · difference · exclusion · subtract
/lN/opacity (N = 1–4)0 – 11layer opacity
/pal/0/r0 – 10.05ink 0 (near-black), r channel
/pal/0/g0 – 10.05ink 0 (near-black), g channel
/pal/0/b0 – 10.05ink 0 (near-black), b channel
/pal/1/r0 – 10.92ink 1 (red), r channel
/pal/1/g0 – 10.1ink 1 (red), g channel
/pal/1/b0 – 10.14ink 1 (red), b channel
/pal/2/r0 – 10.1ink 2 (blue), r channel
/pal/2/g0 – 10.3ink 2 (blue), g channel
/pal/2/b0 – 10.95ink 2 (blue), b channel
/pal/3/r0 – 10.98ink 3 (yellow), r channel
/pal/3/g0 – 10.8ink 3 (yellow), g channel
/pal/3/b0 – 10.05ink 3 (yellow), b channel
/vec/place0 – 10where the stack renders: 0 scene (behind particles, in the feedback chain) · 1 print (after post, exact ink)
/camera/distance0.4 – 123.5orbit distance from the field
/camera/orbit-3.15 – 3.150orbit angle around the field
/camera/elevation-1.4 – 1.40.34height angle of the orbit
/camera/fov0.2 – 20.9field of view, radians
/camera/focus0 – 123.5focus distance
/camera/defocus0 – 10depth-of-field blur amount
/camera/pan_x-4 – 40sideways pan of the view
/camera/pan_y-4 – 40vertical pan of the view
/camera/at_x-8 – 80where in the world the camera is aimed, X
/camera/at_y-8 – 80where in the world the camera is aimed, Y
/camera/at_z-8 – 80where in the world the camera is aimed, Z
/camera/move0 – 100canned path: off, orbit, sway, push, pull, crane, spiral, look around, fly through, walkthrough, drift
/camera/move_bars1 – 648bars per cycle of the move
/camera/move_size0 – 10.5how far the move travels
/room/brightness0 – 10wireframe room visibility
/room/depth1 – 207how deep the room extends
/room/fade0 – 10.75distance fade of the room lines
/room/converge0 – 10.35perspective convergence of the grid
/room/vanish_x-1 – 10vanishing point, sideways
/room/vanish_y-1 – 10vanishing point, vertical
/room/anchor0 – 10.35where the cloud sits between front and back
/room/embed0 – 10how much the room's perspective bends the cloud
/light/ambient0 – 11how much light there is everywhere; 1 is the unlit picture
/light/shape0 – 11how much a surface's own orientation counts (needs normals)
/light/torch0 – 10lamp 1 rides the camera
/light/N/x (N = 1–2)-6 – 60lamp N position, X
/light/N/y (N = 1–2)-6 – 60lamp N position, Y
/light/N/z (N = 1–2)-6 – 60lamp N position, Z
/light/N/radius (N = 1–2)0.05 – 81.5lamp N reach
/light/N/level (N = 1–2)0 – 20lamp N brightness
/light/N/hue (N = 1–2)0 – 10lamp N colour
/light/N/tint (N = 1–2)0 – 10how much of lamp N's colour to use; 0 is white
/sun/level0 – 20directional key brightness (needs normals)
/sun/azimuth-3.15 – 3.150.8which way the sun is, around
/sun/elevation-1.57 – 1.570.6which way the sun is, up
/sun/hue0 – 10.12sun colour
/sun/tint0 – 10how much of the sun's colour to use; 0 is white
/gravity/amount0 – 10master depth of the gravity layer
/gravity/N/x (N = 0–3)-3 – 30well N position, X
/gravity/N/y (N = 0–3)-3 – 30well N position, Y
/gravity/N/z (N = 0–3)-3 – 30well N position, Z
/gravity/N/strength (N = 0–3)-2 – 20pull (positive) or push (negative)
/gravity/N/radius (N = 0–3)0.05 – 41well reach
/gravity/fire0 – 160fire gravity scene 1–16 on change; 0 = none
/gravity/time0 – 602gravity blend time, seconds
/gravity/curve0 – 410 linear · 1 smooth · 2 ease in · 3 ease out · 4 cut
/gravity/auto0 – 10gravity autopilot on/off
/gravity/bars0.25 – 164bars between gravity autopilot steps
/bg/red0 – 10.004background red
/bg/green0 – 10.004background green
/bg/blue0 – 10.008background blue
/bg/alpha0 – 11background opacity; 0 delivers the field on nothing
/preset/recall0 – 640recall preset N on change; 0 = none
/scene/fire0 – 160fire scene 1–16 on change; 0 = none
/scene/time0 – 602scene blend time, seconds
/scene/curve0 – 410 linear · 1 smooth · 2 ease in · 3 ease out · 4 cut
/scene/auto0 – 10scene autopilot on/off
/scene/bars0.25 – 164bars between scene autopilot steps
/deck/select0 – 240turn to page 1–24 on change; 0 = none
/column/fire0 – 160fire column 1–16 — the scene pad and the gravity pad of that number, together
/record/active0 – 10record the master to a PNG sequence; 1 starts, 0 stops
/master/dim0 – 11master fader

Files and folders

~/.config/vizz/projects/<show>/One show — everything below this line lives in one of these
  presets/Your saved looks, one JSON each
  patches/Modulation graphs
  grid.jsonThe scene grid, as the live deck left it
  gravity-grid.jsonThe gravity grid, likewise
  decks.jsonThe set list: every page of pads, and which one is live
  macros.jsonYour fader assignments
~/.config/vizz/open.jsonWhich show is open
~/.config/vizz/midi.jsonYour controller map — the rig, so it stays put when the show changes
~/.config/vizz/settings.jsonOutput size, audio device, loaded clouds, fullscreen — the rig too
~/Movies/vizz/Recordings (macOS; ~/Videos/vizz/ elsewhere)

Built-in presets are compiled into the binary rather than written to disk, so they are always present, cannot be half-installed, and cannot be lost by clearing the config directory.

Upgrading from a build without shows moves what was in ~/.config/vizz/ into projects/Show 1/ on first launch. Nothing is copied and nothing is left behind.

Command line

vizz --help                       # every flag
vizz --width 1920 --height 1080   # output size for this run
vizz --fullscreen --monitor 1     # start on a projector
vizz --ndi --no-syphon            # NDI only
vizz --audio-device "Scarlett"    # match an input by substring
vizz --list-audio                 # print input names and exit
vizz --cloud scan.ply             # load a cloud at startup
vizz --osc-port 7001              # listen somewhere else
vizz --headless --frames 600 --report bench.json

On macOS, double-clicking the app runs 1280×720 with OSC on 7000 and Syphon on; the window title shows the live settings. Flags need a terminal run.

Troubleshooting

I loaded a cloud and nothing changed

Loading one points /shape/mode at the cloud pair for you, so the usual cause is something moving it back: a preset, a scene, or a modulation route driving /shape/mode. Check what the shape group's mode row reads — cloud pair is the position that shows clouds — and whether it carries a ~.

The picture goes white and stays white

/fx/trail is very high and the frame is saturating. Bring it down. (It is capped below 1.0 precisely so this is recoverable.)

Nothing reacts to the music

Check the panel's audio section shows a device and the meters are moving. If the bars move but nothing on screen does, no modulation is routed yet — see the graph. If the bars are pinned to full, press fit.

My controller does nothing

Open the panel's midi section: if the device is not listed, it is a connection problem, not a mapping one. If it is listed, arm a learn and watch the echo line — it names whatever arrives.

The receiving app cannot see vizz

Check the status line: each output has a dot, green when live. Syphon is macOS-only. NDI needs its runtime installed, and the panel says so if it is missing.

I set layer parameters and nothing changed

Check the layer's kind is not off — kind 0 removes the layer regardless of its other settings — and check /vec/place: in print placement the stack replaces the finished frame, so if another look is on screen the stack may be in scene placement behind an opaque particle field. Recalling a vector preset resets all of this.

Frame rate is low

Open health in the panel for frame-time percentiles and the over-budget count. Lower the render multiplier first, then /particles/count. Heavy feedback plus glow at 4K is the usual culprit.

It asks twice before quitting

That is deliberate. Esc is one key next to nothing, and a single press ending the show is the one destructive keystroke worth guarding.