Feed it video, camera, or screen capture and route it through stacked real-time GLSL shaders — generative patterns, kaleidoscopes, feedback, colour, distortion — with every parameter tweakable live. Audio, LFOs, and a tap-tempo BPM clock can modulate any parameter. Record output as video. Cast to a second screen for projection.
Panel
◀ tabTap the tab at the bottom centre of the screen to open / close the control panel
grip stripTap the grip at the top of the panel to close it. Drag it up/down to resize the panel height
SHADERS AND FX CHAINSFolds away the preset bank and the GEN and FX chains in one go, leaving the mode buttons, the source controls and the param sliders. The source controls have their own SOURCE header above them and fold separately. Handy on a phone when you only want to ride the sliders. Whichever way you leave it is remembered between sessions
PARAMS headerThe slider area has its own header above it, which folds the sliders away the same as any other section and names the shader they belong to — so you can still see what is selected with the sliders hidden
section headersEvery heading except MODE — SOURCE, SHADERS AND FX CHAINS, PARAMS, GEN SHADER, FX SHADER, VIDEO, LFO, AUDIO INPUT, MIDI, MISC — is a show/hide toggle. Tap one to fold that section away; the arrow on the right points down when open and right when closed. Useful on a phone where the panel would otherwise be a long scroll. VIDEO, LFO, AUDIO INPUT, MIDI and MISC start closed since they are mostly set-and-forget; SOURCE, GEN SHADER and FX SHADER start open. SOURCE is the open/pause row, the transform row and the speed and in/out sliders — fold it once a clip is running the way you want and the panel gets most of a screen shorter. MISC also holds ZOOM, RES and RENDER CAP, so open it if you are hunting for those. What you collapse from then on is remembered between sessions
MODE buttonssampler / shader / live sit at the top of the panel, directly under NEW / SAVE / LOAD / SHARE / CAST, so they stay visible instead of scrolling away with the rest of the body
RNDRandomise, hard left on the top row in the label column. SEQ takes the position beside it in SAMPLER; in the other two modes that position is blank. Fills the GEN chain with 4 different shaders and the FX chain with 4 different effects, rolls every param, picks blend modes and amounts, re-rolls the per-slot seeds, re-rolls the shape, AMT and period of all three LFOs — AMT signed, so about a quarter of them come up inverted — and makes two to four param bindings across them, each landing well up the influence range so a bound parameter visibly moves. GEN slot 1 is always left on normal at full amount — it composites onto black, where a subtractive mode is an immediate blackout whatever follows it. It also switches to SHADER. Not because the chain would be bypassed — the slots it builds arrive live — but because slot 1 lands on normal at full amount and covers the source completely, so SHADER is simply where the result is. When clips are loaded it also fills all eight sequencer steps from them, never the same clip twice running and never the camera, so a random patch arrives with a sequence under it; with no clips loaded the steps are left alone, and the toast says which happened. The STEPS row is a SAMPLER row, so a randomise done from anywhere else fills it out of sight — it is waiting there when you switch back. It is set apart from the other controls because it replaces both chains wholesale
ZOOMGlobal zoom slider, in the MISC section near the bottom of the panel — it scales the canvas output and is useful when the device resolution is larger than the display area. Tap 1:1 to reset. It lives down there rather than with the chains because it is a set-once control, not something you ride mid-set
RESRender scale — ½ / ¾ / 1×, on the zoom row in the MISC section. A fraction of the display resolution, so it always tracks the screen you are on. Lower means fewer pixels through the shader chain, which is the first thing to reach for when a deep chain drops frames
RENDER CAPAn absolute ceiling on the internal buffer, on its own row in the MISC section — off / 1080 / 4K, defaulting to 4K. Where RES is a fraction of whatever display you plug into, this is a hard pixel budget that does not care how big the screen is. It bounds GPU memory on large displays and does nothing at all below the ceiling. Saved per device, and deliberately not part of presets or share links
resolution readoutThe figure at the end of the RENDER CAP row is the buffer size actually in use, after RES and RENDER CAP have both been applied. A ▼ after it means the cap is currently biting — without that you could not tell a capped picture from a small window
param slidersThe upper slot shows the active shader's parameters — scroll it independently. The lower body scrolls separately
Signal flow strip
GEN rowShows the generative shader chain as four fixed boxes on the same column ruler as every other row in the section. A block sits in the box you put it in and stays there — a single shader can live in box 4 with boxes 1 to 3 empty, so you can lay out a chain before you have filled it. Boxes run left to right in signal order, and empty ones cost nothing: a chain of one renders identically wherever it sits. A filled block carries a short abbreviation — hover for the full name — and clicking it selects its params.
Adding or selecting a GEN does not change mode. The chain composites over the base layer in every mode — the clip in SAMPLER, the camera in LIVE, black in SHADER — so a gen dropped in while a clip is playing lands over that clip and stays there. It arrives un-bypassed even though entering SAMPLER bypasses the chain, and the param sliders, LFO, audio and MIDI bindings all follow it wherever you are. This used to jump to SHADER, which threw away the clip in order to show the thing that was meant to sit on top of it
FX rowShows the FX chain on the same four boxes as GEN directly above it. Same rules: blocks hold their box, empties are free positions, and the order the boxes run in is the order the effects apply. GEN blocks composite onto each other; FX blocks run in series
drag to reorderDrag a block onto another box to move it there. If that box is occupied the two swap — the block you dragged takes the target and the one that was there takes the box you came from. No untouched block moves, so a chain can be laid out position by position
drag from gridDrag a GEN or FX button from the grid below onto a box in the strip. An empty box takes it; an occupied box is replaced, because with fixed boxes there is no gap to squeeze into and replacing is the only thing that puts the block exactly where you dropped it. Dragging the same GEN shader more than once gives you duplicate instances, each with its own random seed so the procedural patterns differ
double-clickDouble-click a block to bypass (disable) it — shown dimmed with strikethrough. Double-click again to re-enable. The shader stays in the chain but is skipped during rendering
top rowEverything that is not a chain, on one line: RND hard left in the label column, then SEQ, then SRC and the camera toggle, then a blank slot and BANK, OVR and CLR. SEQ is only there in SAMPLER, since nothing else plays clips; in the other modes that position is left blank rather than closed up, so SRC and CAM do not move sideways with the mode. The gap before BANK separates the source controls from the bank controls. Below it the strip reads top-down in the order the signal actually travels: clip → gen → fx, with the saved presets last. The bank is storage rather than signal, so it sits under the chains rather than between the controls and them
preset rowAt the foot of the section, under the GEN and FX chains, one block per saved preset with the loaded one lit. It sits there rather than up with the controls because the bank is storage rather than signal — the rows above it read clip → gen → fx in the order the picture is built. It starts hard left, running under the label column as well — it is the one row here that is not on the section's shared ruler, because a preset is not a chain position and there is nothing above or below for it to line up with. That buys most of another block per line. Click any block to jump straight to it: no dialog, no confirmation. [ and ] step backwards and forwards through the bank, which is the fastest way to work through a set. The row wraps to two lines and holds eight; past that it pages
BANKReads just BANK while everything fits. Once you have more than eight presets it reads BANK1, BANK2 and so on, and clicking it steps to the next page and wraps. Saving a preset, jumping to one, or stepping with [ and ] all pull the page to wherever the lit block is, so the loaded preset is never on a page you cannot see
NEWIn the header beside SAVE. Starts a fresh patch and always asks first: SAVE… opens the save dialog and starts fresh only once the preset is stored (cancelling it keeps the patch you had), DISCARD starts fresh straight away, CANCEL or Escape does nothing. Fresh means the chains, params, modulation, LFOs and tempo the page opens with. The mode, clips, camera, sequence, orientation, playback and crossfade settings are left alone, and in SAMPLER and LIVE the new GEN chain arrives bypassed so the source stays on screen
OVROverwrite a saved preset with the patch you have now, keeping its name. Three taps, all on the strip — no dialog. Tap OVR and it lights; tap the preset you mean to replace and it lights, with its name in the toast; tap that same block again to write. Tapping a different preset re-aims instead of writing, so a slip moves the target rather than destroying the wrong one. Escape, a second tap on OVR, or turning the page cancels. While OVR is armed a click on a preset never jumps, so it will not throw away the patch you were about to save
CLRTwo jobs, and the button says which one the next tap does.
With a preset lit in the bank row, CLR is magenta and deletes just that one, on a single tap. No arming: the highlight already is the selection, so a second tap would only confirm something the strip is showing you. Deleting one entry re-lights nothing, so the very next CLR arms the full wipe instead.
With nothing lit, CLR is red and deletes every saved preset. It arms rather than firing: the first tap names how many it is about to delete, the second does it. Escape, or a tap on any other control, cancels.
Neither has an undo, and the bank does not travel with the file, so EXPORT BANK in the SAVE dialog is the only backup. Presets already loaded stay on screen; it is the saved bank that goes
what a jump restoresEverything the preset captured, exactly as saved — including the mode. A preset saved in LIVE will start the camera when you jump to it, and one saved in SAMPLER will drop you back to the loaded clip. Worth knowing before jumping mid-set
drag off stripDrag a block out of the strip and release to remove it. The box it was in is left empty and nothing else shifts, so you can pull an effect out, watch without it, and drop it straight back into the same box. The last GEN shader is the exception and cannot be dragged away
empty boxClick an empty box to select it — it lights up, and it is the only lit box in its row — then click any shader or effect in the grid below and it drops into that box. This is the no-dragging route to building a chain in whatever order you like, and it is the easy one on a phone. Clicking the lit empty box again, or clicking any filled block, selects that block instead
Modes
SAMPLERPlays a loaded video file as the source texture — open file, drag onto canvas, or use a previously recorded export. Arriving here bypasses the whole GEN chain so the video shows straight through: both this and LIVE are about the source, and landing in one with the shader stack painted over the top hides the thing you just switched to look at. The chain is kept intact — the blend button in the source row puts it back in one tap, and a GEN you add while already in SAMPLER arrives live rather than bypassed, since you added it to see it
SHADERGenerates visuals from GLSL shaders — no video source needed. Optionally blend a video layer over the output. Arriving here undoes an all-bypassed chain, since SAMPLER and LIVE both leave one behind and you would otherwise land in the mode built for shaders and see none. If you have muted only SOME slots from the flow strip that selection is kept — only the everything-off state is cleared
LIVEUses the device camera as the source texture in real time. Like SAMPLER, arriving here bypasses the GEN chain so the camera shows straight through
ENTERCycle SAMPLER → SHADER → LIVE (keyboard). Each mode arrives set up for what that mode is about — see the three entries above
Video source (SAMPLER)
open fileBrowse for a video file — mp4, webm, mov and most common formats supported
drag & dropDrop any video file directly onto the canvas
capture screenShare your screen or a window as a live source — browser will prompt for permission. It takes over the clip position that is playing and hands it back when the capture ends, however it ends: from the browser's own stop-sharing bar, by selecting another clip, or by loading a file. The clip's name, in/out points and playhead come back with it. Not to be confused with snap png beside it, which writes a still of the output rather than taking a screen in as a source
SPACE / RPlay/pause forwards · Play/pause backwards
in/out pointsTap the in→out→clr button (or 0 key): first tap sets in-point, second sets out-point, third clears both. Video loops between the two points
flip V / rot 90°Flip video vertically or rotate 90° clockwise (cycles 0/90/180/270)
GEN shaders — generative layers
tap GEN buttonPuts that shader in the selected GEN box — the lit block, or the lit empty box — replacing whatever was there. Every other box stays exactly as it was. The box keeps its blend mode and amount; the shader's params start from their defaults. Tapping the shader the selected box already holds changes nothing except lifting a bypass
removeDrag the block off the strip. A grid tap never removes. The keys 4–9 still add and remove, in SHADER mode
drag to stripDrag a GEN button onto the flow strip to insert it at a specific position in the chain
multi-layer blendWhen 2+ GEN shaders are active, a BLEND row appears in params — drag to set mix, tap the mode label to cycle blend modes
4 – 9Keyboard shortcuts to toggle gen shader slots 1–6 — the first six of the fifteen, in table order: plasma, kaleidoscope, tunnel, flowing-colours, hypnotic-rings, squarewaves. The other nine are panel-only. They act in SHADER mode only: in SAMPLER and LIVE the digits are ignored, since a chain edit there is a change to what is painted over the source rather than to what is on screen. Use the grid or the flow strip in those modes
style slidersplasma, flowing-colours and zoom-clouds each carry a style selector with eight variants, plus extra shaping params. In every case style 0 with the new params at zero is exactly how that shader behaved before they were added, so old presets are unchanged — the variants are opt-in
plasmaInterference-field generator. speed/scale/warp/palette work as before. style picks the family, snapping through eight types: 0 classic (the original four-sine field), 1 fractal (the same field stacked over octaves), 2 warped (domain-warped fractal — the field displaces its own coordinates, giving slow organic cloud motion), 3 ridged (creased at every zero crossing, veined and marbled), 4 marble (a sine banded by turbulence — wood-grain and stone), 5 ripples (concentric rings modulated by the fractal field), 6 julia (an actual escape-time fractal, animated by walking c around a circle and coloured by banding the orbit-trap distance; scale is the zoom here rather than frequency — the heaviest style, drop render scale if it chugs), 7 flow (the field advects along itself into streaming filaments). detail sets fractal depth, 1 to 4 octaves, and opens up the falloff between them — it does nothing on style 0. contrast squeezes the field toward its extremes, turning smooth gradients into hard bands. fold applies up to three kaleidoscopic mirror-and-rotate passes for self-similar symmetry. drift walks the whole field along a slow bounded orbit so the pattern travels instead of standing still. All five sit at 0 on presets saved before they existed, and style 0 with detail 0 is exactly the old plasma
flowing-coloursBreathing colour-flow field. speed/detail/warp/hue/zoom work as before. style snaps through eight types: 0 classic (the original field), 1 layered (the same field stacked over octaves), 2 warped (the field displaces its own coordinates — slow organic churn), 3 veins (folded at every zero crossing), 4 contour (topographic banding), 5 vortex (rotated by radius so the field winds into a spiral), 6 moire (two counter-rotated copies multiplied, giving beat patterns a single field cannot make), 7 liquid (soft-thresholded into rounded masses that merge and split). layers sets octave depth 1 to 3 — each octave is six sines so it costs more than it looks, and it does nothing on style 0. contrast pushes toward the extremes, widening the flat saturated regions. fold adds up to three kaleidoscopic mirror passes. steady is the useful one live: the original multiplies the whole field by sin(t/10) so it periodically washes out to flat — at 0 that behaviour is kept, at 1 the amplitude holds constant. vivid boosts saturation. All six sit at 0 on presets saved before they existed, and style 0 with steady 0 is exactly the old flowing-colours
zoom-cloudsDomain-warped cloud field. speed/detail/warp/hue/zoom work as before. style snaps through eight types: 0 classic, 1 billow (folded noise — cumulus rather than haze), 2 wispy (finer scale, thin cirrus), 3 marble (the field banded through a sine), 4 ridged (inverted turbulence, sharp veins filling the frame), 5 storm (extra warp on folded noise, dark and violent), 6 contour (topographic bands), 7 streaks (stretched horizontally into wind-blown layers). contrast is the one worth reaching for: the original ramp blows about half of a typical frame out to flat cream, so this pulls the ramp gain back as you raise it while steepening the curve — you recover the washed-out highlights and get more definition at the same time, rather than trading one for the other. rough raises the octave falloff from the original 0.5 up to 0.78, making the clouds progressively grainier — the fine detail gains weight relative to the broad shapes, and the field is renormalised so raising it adds texture rather than just brightening everything. relief fakes lighting from the field's gradient, giving the clouds volume instead of a flat wash — it is normalised against render resolution, so it looks the same at every RES setting rather than changing strength when you drop the render scale. drift runs the outer warp layer faster than the inner one so they shear past each other rather than boiling in place. palette blends the fixed blue-to-cream ramp toward a full colour palette. All six sit at 0 on presets saved before they existed, and style 0 with rough 0 is exactly the old zoom-clouds
voronoiCellular / particle field. density now scales up to ~44 cells across; speed sets motion; edge softens cell boundaries; palette picks colour. mode selects the look: cells (distance-shaded), borders (cracked-cell network), mosaic (flat colour per cell), or particles (dark field of dots). size sets the dot radius and glow adds an additive halo, so cell centres render as points on top of any mode. swarm blends independent jitter into coherent flow-field motion where neighbouring points stream together like a flock. warp bends the lattice for organic, non-grid cells
squarewavesWave pattern. amplitude, wavetype, frequency, hue, zoom, softness and rotation as named. detail adds layers and a motion trail. warp bends the waves. fold adds symmetry. relief adds fake lighting. audio brightens columns with the live audio spectrum (needs audio input). tilt, spin-x, spin-y, spin-z, depth, glow and layers put the pattern on a plane in 3D, as on hypnotic-rings: tilt leans it back, the spins turn it continuously (the middle of each is still), depth sets the perspective, glow turns the bands into thin glowing lines, and layers moves red and blue onto planes in front of and behind green. High detail is expensive, and layers costs about three times as much.
oscilloscopeDedicated audio-waveform visualiser (needs audio enabled — mic/tab/video). style picks the display: line, filled, mirrored, bars, or radial (circular scope). thickness sets stroke width, scale/gain set the vertical size and sensitivity, hue the colour. persistence leaves a slowly-fading trail of past waveforms (up to ~1s), outline draws a bright edge on the filled styles, glow adds a halo, brightness lifts the background. When audio stops the trail ages out and fades on its own. Use an 'add' blend mode to overlay it on video/other layers
kaleidoscopeRadial mirror pattern generated from its own wave field — unrelated to the mirror and kaleido-warp effects, which fold incoming video instead. sides snaps from 3 to 12 segments, spin rotates the fold (centre is still, either side turns opposite ways), zoom scales the pattern inside each wedge, palette picks the colour ramp. The fold angle is eased so the seam where segments meet stays invisible while the mirror lines themselves stay sharp
tunnelPerspective tunnel — rings rushing toward you with segments running down the walls. speed drives the travel, segs sets how many segments go round (rounded to a whole number so the seam at the back closes cleanly), twist shears them into a helix that tightens with radius, zoom and palette as usual. The centre fades out rather than collapsing to a point
hypnotic-ringsThree sets of rings, one per colour channel, from moving centres. speed drives the movement, freq the ring spacing, orbit how far the centres move, hue shifts the colour, zoom scales it. softness goes from hard bands to smooth gradients. wavetype changes the ring shape from sine to triangle to sawtooth. drift adds extra wandering so the pattern does not repeat. The rest put the pattern on a plane in 3D: tilt leans it back (0 is flat to the screen), spin-x, spin-y and spin-z turn it continuously about each axis (the middle of each is still, either side turns one way or the other), and depth sets how strong the perspective is. layers moves the three colours onto separate planes in front of and behind each other, so they slide apart as the plane turns. glow turns the bands into thin glowing lines. Far off on a tilted plane the rings fade to a soft haze rather than shimmering.
beamsTwo star emitters, each star on its own radial lane. stars sets how many (up to 500). e1-speed and e2-speed: above the middle stars fly outward, below it inward. e1-trail and e2-trail stretch stars into streaks. e1-size and e2-size set the star size. e2-x and e2-y move the second emitter; the first stays centred. palette and zoom apply to both.
gamma-rayThe flecks and streaks a camera sensor picks up from a radioactive source, new every frame. density sets how many hits. brightness how bright they are. size sets their size (from under a pixel to about 8 pixels across) and size-var how much that varies, from all alike to a quarter to four times the size. clump makes hits arrive in groups, with smaller hits scattered round each one. streaks turns a share of hits into short tracks at random angles, as from particles crossing the sensor at a shallow angle. bayer makes some hits light a single red, green or blue, as on a real colour sensor. glow adds a soft halo. colour at 0 is white; raising it tints the hits through green, blue and red. Sizes are in render pixels, as on a sensor. mode switches between sensor (the above) and cloud, a cloud chamber: particle tracks that condense, then fade and drift over lifetime (0.3 to 3 seconds), with mist adding a slow haze and droplet sparkle. In cloud mode five sliders change names: tracks sets how many tracks appear, width the droplet size, muons how many long straight tracks cross the whole frame, alpha the share of short thick alpha tracks (densest toward their end), field the strength of the magnetic field that bends the other tracks into arcs (stronger is tighter), and source the share of tracks that burst out of a source in the middle. Two sliders at the bottom are for cloud mode only: spirals is the share of slow particles that curl inward in tightening spirals, and bubbles sets how closely the droplets that make up each track follow one another, from sparse dotted trails to dense ones. Tracks are made of individual droplets of varying size and brightness, scattered a little to either side and spreading as they age; alphas are dense bands of droplets. brightness, colour and glow work as in sensor mode. Use add or screen blend over video.
wavesThe plainest generator in the table and the cheapest to run. Stacked sine bands rippling across the frame: frequency sets how tightly they pack, speed how fast they travel, count how many layers stack, palette picks the colour ramp and zoom scales the whole field. Five params, no selector, no octave stack — it is the one to reach for as a base layer under something expensive, or when a deep FX chain has already spent the frame budget
fractalA 3D fractal. type picks it: quaternion (a 4D Julia set; shape-a picks the form, shape-b the cross-section you see), mandelbox (folded architecture; shape-a goes from chunky to lacy, shape-b changes the shape without changing its size), mandelbulb (shape-a is the power, from a few lobes to many; shape-b twists it), menger (a sponge; shape-a is the scale, the middle is the classic sponge; shape-b turns each fold for crystal and lattice variations), sierpinski (a tetrahedron of tetrahedra; shape-a is the scale, shape-b turns each fold) or maze. For the first five: morph makes the shape move slowly (0 holds it still); detail adds detail and costs performance, so lower it first if frames drop; spin orbits the camera (the middle of the slider is still), tilt raises or lowers the view, zoom moves the camera in, and at the top it goes inside the object; speed drives morph and tumble; hue, palette, glow and shade set the colouring. maze is a flight through an endless maze whose walls contain smaller mazes, and its sliders change names: speed sets flight speed (0 stops), fov the lens width, turns how much the path wanders, width and density the corridor size and how many walls are open, circuits and windows two kinds of wall lighting, detail the smaller maze levels (the main performance control), hue, saturation and glow the colour, fog the haze. The background is black, so use screen or add blend over other layers. Presets with the old quaternion, mandelbox or maze-flight load as fractal with that type.
emitterParticles thrown out from a point. shape picks one of fifteen shapes, alternating flat and solid (dot, sphere, square, cube, tri, tetra, star, dodeca, ring, torus, cross, jack, diamond, octa, spark). Shapes face their direction of travel. origin-x and origin-y place the emitter. count is how many particles exist at once (8 to 512). rate is how many are emitted per second (0.25 to 250). A particle lives count ÷ rate seconds. reach is how far particles travel. size-start and size-end set the size at birth and death; below the middle of the slider the size is negative, which flips the shape. spin rotates particles over their life (middle is none). tumble gives each particle its own random rotation. depth turns it into a starfield: particles come from a distant point toward the viewer, growing as they approach. opacity, glow, hue-start and hue-end set the look; particles change from the start hue to the end hue over their life.
starsA warp starfield: stars come from far away toward you and rush past the edge of the frame. speed sets how fast; the middle of the slider is still and below it they fly away from you. density sets how many stars. size and size-var set the star size and how much it differs between stars. streak stretches each star along its path into a trail that fades toward the tail; it lengthens with speed, as a long exposure would. curve bends the paths into a spiral, either way from the middle. colour sets how far stars move from white toward their own hue, saturation how strong that hue is. opacity-var makes some stars fainter than others. twinkle makes a share of the stars pulse, and how deeply. ghosts replaces the streak with up to eight separate dots along the path (0 is a continuous streak). origin-x and origin-y place the point the stars come from, and drift makes it wander. dispersal sets how far across the frame stars start: low gives a tunnel from one point, high stars that appear anywhere. The background is black, so use screen or add blend over other layers. For the slow fading persistence of the original, put feedback after it.
FX shaders — effects pipeline
tap FX buttonPuts that effect in the selected FX box — the lit block, the lit empty box, or box 1 when the row is empty — replacing whatever was there. Every other box stays exactly as it was. The box keeps its blend mode and mix, except across a swap to or from feedback, whose row means something different. Only one feedback slot is allowed. Remove an effect by dragging it off the strip. Badge shows position
drag to stripDrag an FX button onto the FX row of the flow strip to insert it at a specific position
fx blend + mixEvery FX slot has its own BLEND row at the top of its params, same as a GEN layer. Tap the mode label to cycle the compositing mode and drag the mix row to set how much of the processed image comes through. mix is wet/dry: 1.00 is the full effect, 0.00 is the untouched input. With a non-normal mode the effect output is composited back over its own dry input — e.g. difference on an edgy effect leaves only what the effect changed, add keeps the original and layers the effect's brightness on top, and multiply darkens where the effect is dark. The slot still feeds the next one in the chain, so modes stack down the pipeline. FEEDBACK is the exception: it accumulates across frames rather than processing an input, so it sits outside the chain and its BLEND row does nothing. The trail is always composited with screen at a fixed quarter strength, which is what makes it build up frame on frame. Use its own decay and spread params to shape it, and note that its blend-mode param is a different control again — that one reshapes the decayed trail itself
fx off btnClears every FX shader, its params, and mod bindings from the chain instantly — not reversible from the button itself. For a temporary, reversible bypass, double-click a block in the flow strip instead
bitcrush 1-bitEnable the 1-bit toggle in bitcrush params to reduce to pure on/off based on luma. Hue slider sets the "on" colour, threshold sets the cutoff
asciiConverts the image to coloured ASCII characters. Char-size sets character size, invert flips the brightness mapping, mix blends with the original, variation adds per-cell randomness so uniform areas show different characters — it jitters the brightness each cell reads before choosing its glyph, so the character mix loosens while the image still reads. charset picks which alphabet the glyphs come from: 0 all (every block together — what presets saved before this param get), 1 ascii (the full 95-character printable set, the default for new instances), 2 ascii+katakana, 3 katakana only, 4 CJK only. Each set is ranked by ink coverage on its own, so every charset gives a correct dark-to-light ramp rather than a slice of someone else's. rate sets how much the characters churn: it raises both the tick speed — from about one change every 2.5 seconds up to 14 a second — and how far each re-roll is allowed to move along the character ramp. Because the colour of each cell is sampled from the video every frame regardless, a low rate gives you a character that holds still for a beat while its colour keeps shifting with the footage, and a high rate gives a busy flickering lattice. It works on its own and stacks on top of variation
halftoneClassic RGB halftone screen — each colour channel is rendered as a grid of dots at its own angle (R-angle, G-angle, B-angle) and cell size (R-size, G-size, B-size). Default angles approximate traditional printing screens (R=15°, G=75°, B=0°). Mix blends with the original image
levelsTone-curve adjustment (Photoshop/GIMP Levels) — shows a live curve canvas with 5 control points (blacks, shadows, midtones, highlights, whites). Drag a point up/down to reshape the tone curve. Bezier tangent arms show curve slope. All 5 points support audio, LFO, and MIDI modulation via the param sliders below the canvas
sample-holdFreezes the frame and takes a new one at intervals. sync: free takes a new frame at random times, faster as rate goes up. tempo takes a new frame on each division of the BPM set in the LFO section (TAP sets beat 1). beat takes a new frame on every division-th beat detected in the audio input (bass hits); it needs an audio source. division: 1/4 to 8 beats (in beat mode below 1 counts as 1). Effects after it keep running on the frozen frame. Each sample-hold slot works independently.
glitchDigital glitch. intensity shifts horizontal slices. rate sets how often the glitch changes. channel splits the colour channels. slices sets the number of bands. variation groups and stretches slices. noise adds block drop-outs and colour errors. crush reduces the number of colours. wave adds a horizontal wobble. chaos makes it irregular: calm and heavy stretches, and random strength on each hit.
feature-dots (retired)Not in the effects grid and cannot be added to a chain. flow-dots replaced it: it answers the same brief with particles that actually travel and carries the link net as well, so nothing was left that only feature-dots could do.
The entry still exists, and holds its place in the table on purpose. A shader is stored as a number, so removing one renumbers every effect after it — scatter and flow-dots would shift down and every preset and share URL naming either would silently open as the wrong effect. Keeping the slot costs one passthrough draw and keeps every other patch honest. An old patch that used it still loads; that slot passes its input through unchanged rather than drawing dots
scatterCuts the frame into a grid and rearranges the cells. grid sets the number of cells. shuffle sets how far cells move, amount how many move. pixelate flattens each cell. rate re-arranges them over time (0 holds still). seam darkens the cell borders. edge makes the cell borders transparent, so the unshuffled picture shows through, fading to solid toward the cell centre; higher values widen the fade. mode: scatter, swap, rows, columns or spin. stagger makes cells change at different times (only with rate above 0).
feedbackTrails. It keeps a history and mixes each new frame into it. place: top (default) runs it after the whole FX chain; in place runs it at its own position, so later effects process the trails. Several feedback slots each keep their own trail. blend sets where the blend mode applies: loop mixes it into the trail itself, output applies it when the trail is laid over the picture. inject sets how strongly each new frame goes into the trail. decay sets the trail length. delay sets the time between trail updates (0 to 2 seconds): at 0 the trail updates every frame; above it each update adds one echo, so the echoes are spaced out in time while the live picture keeps running smoothly. step sets how much dimmer each echo is than the one before (0.25 = a quarter dimmer); at 0 decay sets it instead, above 0 step replaces decay. With delay set, decay counts echoes rather than frames. spread blurs the trail as it ages (keep it low). zoom and rotate move the trail each frame so echoes separate; centre-x and centre-y set the centre point. trail picks the ageing style: plain, cycle (colour shifts), edge (outlines only), crisp (separate echoes) or ember (fades through red).
flow-dotsDots that sit on image features, move with the motion in the picture, and respawn. pitch sets dot spacing, dot-size their size, jitter how far they stray. sensitivity sets how easily features are detected. gamma evens out strong and weak features; lower it to get dots on faces and other low-contrast areas. detect chooses corners (0), all edges (0.5) or the opposite of features (1). flow sets how closely dots follow the motion. life sets how long a dot lasts. fall moves all dots in one of eight directions; fall-speed sets how fast. tint mixes from the picture's colour to a drifting palette colour. link draws lines between neighbouring dots (0 is off). The dots are on black; use screen or add blend. Needs float render targets (see the I overlay).
mirrorReflects the frame about one or both axes. axes picks the arrangement, rotation turns the mirror line before the fold so the seam can run diagonally rather than square, and centre-x / centre-y move the fold origin off the middle of frame. Distinct from kaleido-warp, which folds into radial wedges — this one is straight reflection
invertPer-channel inversion. R-invert, G-invert and B-invert each flip one channel, so inverting one or two gives a colour shift rather than a negative — all three together is the full negative. amount blends the result against the original, so it works as a strength control. Defaults are all four at 1, which is a straight negative
bitcrushTwo reductions in one effect. block-size pixelates, color-depth quantises each channel to a small number of steps, and gap draws a grid line between blocks for a hard LED-panel look. mix blends against the original. See bitcrush 1-bit below for the threshold mode.
block-size runs on an exponential scale: 1 px at the bottom, 512 px at the top, doubling every ninth of the travel. At the top that is under four blocks across a 1080p frame. The slider is coarse at the far end by design — a linear or squared map spends nearly all of its travel in the range where the picture is still legible and never reaches a size that reads as a handful of big cells. It costs the same whatever the setting; there is no loop, just one texture read per block.
Each block takes the colour of the single pixel at its centre rather than the average of what it covers. On stills that is invisible. On moving footage at large sizes it flickers, because one pixel is standing in for a quarter of a million, and whatever crosses that exact point sets the colour of the whole cell
grainFilm and tape texture as one effect. scanlines darkens alternate rows, noise adds per-pixel grain, luma-crush quantises brightness so the noise sits in visible steps rather than dissolving smoothly, and speed sets how fast the noise pattern is re-rolled — low values leave a fixed dirt pattern sitting over the image, high values give live static
wobbleSine displacement on both axes independently. X-amp and X-freq set how far and how tightly the image ripples horizontally, Y-amp and Y-freq the same vertically. Setting one axis to zero amplitude gives a clean single-axis wave; running both at different frequencies gives the drifting interference pattern
vhsAnalog tape emulation. chroma pulls red and blue apart horizontally, scanlines darkens alternate lines, noise adds per-pixel grain, and tracking jitters whole scanlines sideways at random — the tape-alignment wobble. A slight desaturation and warm tint are applied on top
posterizeReduces the image to a small number of colour steps — levels sets how many, 2 to 16 per channel. contrast is applied after the quantisation, so it hardens the edges between bands rather than creating more of them. tint-hue rotates the hue of the posterised result, centre being no shift. mix blends back against the original
colorizerReplaces the image colour with a hue derived from its brightness, then scrolls that mapping over time. bands sets how many times the hue wraps across the brightness range, speed scrolls it, spread is the saturation, mix blends back against the original. Unlike hue-cycle the mapping stays continuous, so gradients come out smooth
hue-cycleThe banded counterpart to colorizer: brightness is quantised into steps first and each step gets its own hue, giving flat blocks of colour instead of a sweep. bands sets how many, speed scrolls the hues through them, saturation and amount as usual
hsv-shiftDirect HSV adjustment. hue rotates the whole image (centre is no change), saturation multiplies from a fifth up to double, value from a third up to 1.7x. amount blends against the original, so it doubles as a strength control
kaleido-warpFolds the incoming video into mirrored wedges — the video-processing counterpart to the kaleidoscope generator. sectors snaps from 2 to 16, spin rotates the fold over time with centre being still, and centre-x / centre-y move the fold origin anywhere in the frame
rotate-zoomPlain geometric transform. spin covers a full turn across the slider with centre at no rotation, zoom scales from a tenth up to 4x, and centre-x / centre-y set the pivot. Edges clamp rather than wrapping, so pushing past the frame smears the border pixels
zoom-fxZoom with movement. zoom sets the zoom (0.25× to 3×) about centre-x and centre-y. pulse adds a repeating movement; shape picks sine, kick, square or ramp. rotate turns the picture (middle is none). blur adds radial streaks. travel is an endless zoom: right of the middle zooms in, left zooms out. Keep zoom above about 0.45 on the slider when using travel or rotation to avoid showing repeated edge pixels.
traceGlowing edges that follow motion. It draws the edges of its input and keeps a fading history that moves with the picture, so moving things leave trails. threshold: how strong an edge must be to draw. width: line thickness. detail: fine detail (1) or only large shapes (0). adapt and lift bring out low-contrast detail such as faces: adapt compares each edge to its surroundings, lift boosts weak edges. If flat areas start to sparkle, raise threshold. trail: how long the history lasts (0 is edges only). follow: how far trails move with the motion. smoke: horizontal edges give off smoke that rises and fades. glow: bloom around lines. brightness: line brightness. tint: from the picture's colour to the hue colour. hue-drift: older trails change colour. source: how much of the original picture shows under the lines. invert: dark lines on white. Needs float render targets.
crtA CRT tube. mask picks the phosphor pattern: grille (aperture-grille stripes), dots (shadow-mask triads) or slot (slot mask). pitch sets the size of one red-green-blue triad, from 2 to 9 render pixels. mask-amount sets how strongly the pattern shows; brightness is lifted to make up for it. scanlines adds 576 horizontal beam lines over the picture height (PAL), wider on bright parts; they need about 1150 render pixels of height to show crisply, so at lower RENDER CAP settings they soften rather than shimmer. glow lets bright areas bleed into their surroundings. curve bends the picture like a tube face and darkens the corners. persistence leaves a fading afterglow behind bright parts (0 is none). convergence offsets red and blue from green. mask-rot turns the phosphor mask about the centre of the frame, a full 360 degrees across the slider (0 and the top are both upright), so it can be spun by an LFO without a jump. The mask is fixed to render pixels, so it looks finer at a higher RENDER CAP.
windEdges facing the wind shed particles that drift downwind and fade, like a directional blur made of streaks. direction sets where the wind blows (a full turn; 0 is to the right). speed sets how fast the particles travel; at higher speeds each edge emits more often, so the streaks stay continuous. lifetime sets how long they last before fading out. threshold sets how strong an edge must be to shed anything. side picks which edges shed: windward (the ones the wind meets first), both, or leeward (the ones it leaves). density sets how many particles: low gives separate specks, 1 a smooth smear. turbulence makes the streaks wander. spread widens them as they travel. colour at 0 uses the picture's own colour from the bright side of each edge; moving it up tints the particles through the hues at the picture's brightness, and at the top they are white. emit sets how bright new particles are. It draws on black and is laid over its input by its blend row, screen by default; add makes it brighter, and the amount fades it. Raising RENDER CAP makes the particles finer.
video-feedbackClassic video feedback, like a camera pointed at its own monitor: the picture with copies of itself from earlier moments, each smaller and nested inside the last, heading to a perspective point. steps sets how many copies it takes to reach the point (1 to 60; 10 to start), and they fade evenly from full at the outside to nothing at the point. spacing picks how the copies are spaced: even (equal steps from the edge to the point) or log (each copy the same fraction smaller than the last, like real feedback, crowding toward the point). delay sets the time between copies (0 to 1 second): at 0 each copy is one frame older than the one outside it; above it the copies step in time while the live picture keeps running. point-x and point-y move the perspective point. rotate turns each copy a little more (the middle is none). opacity and blend set how each copy is laid over the larger ones: normal pastes it like a picture in a picture, which gives the classic tunnel of frames on full-frame footage; screen, add, lighten and the rest mix the copies in, which shows stepped trails of things on a black background. hue shifts each copy's colour a little further, for the colour cycling of real feedback. fade darkens each copy further, as a real loop loses light. edge softens the border of each copy, from a hard frame at 0 to a wide feather at 1. The copies are stored snapshots at up to half the render size, so the largest ones are a little softer than the live picture; more steps means smaller snapshots. It is reset when the effect is removed and added again.
Parameters
param sliderDrag horizontally to change value. Tap a row to select it (highlighted). Some params are toggles (☐/☑) — tap to flip
pattern centringEffects built on a repeating grid measure that grid from the centre of the frame, not from the coordinate origin at the bottom-left. Measured from the corner, animating the cell size — from an LFO, say — slides the whole pattern diagonally instead of scaling in place. bitcrush, ascii, halftone and flow-dots now count their grids out from the CENTRE of the frame, so a size sweep grows and shrinks around the middle and whatever is in the centre of shot stays put. halftone applies the same to its angle sliders, which rotate the dot screen in place rather than swinging the whole frame about a corner. gamma-ray, grain, oscilloscope and scatter are unchanged: they gain nothing from it, and scatter's grid has to stay an exact tiling for its swap mode to remain reversible. Existing presets shift by under half a cell standing still; the difference is only obvious in motion
clip slotsSAMPLER holds four clips at once. The CLIP row in the flow strip shows all four positions, filled or not, on the same column ruler as every other row — so the clip you loaded second is always the second block, and reachable by number without looking.
A fifth block, LIVE, is not a clip: it puts the camera in the source position instead of the selected clip, on shift+5 or a tap. It is the same feed LIVE mode uses and follows the same camera controls — front/rear appears in the SOURCE row while it is lit — but it is reached from the other side and changes nothing about the mode. LIVE mode remains its own thing. Tapping any of the four clips takes the camera straight back out, so the row is a five-way switch between four clips and the camera. Switching to or from it is always a cut, never a crossfade: a fade is a composite of two clip elements and the camera is not one of them. The transport, speed and in/out controls go on applying to whichever clip is selected, so it is waiting where you left it when you come back.
Load them with OPEN and a multi-select (they fill consecutive slots from the current one), or shift-drop a file to land it in the next empty slot instead of replacing what is playing. shift+1 to shift+4 jump to a slot; ; and ' step to the previous and next loaded slot, skipping empties — the same gesture as [ and ] on the preset bank. Shifted digits because the bare ones are all live param and gen controls, and a clip jump reloads the source.
Each slot keeps its own in/out points, rate, loop, ping-pong and reverse setting, and its own playhead, so a jump away and back resumes where it was — including the direction it was running in. The clip bank itself is session-local: presets and share links do not carry four files, because four missing-clip prompts before anything plays is worse than one.
Each slot owns its own video element, so a jump is a switch rather than a load — the incoming clip is already decoded and holding a frame. Only the active element plays; the other three sit paused. That is deliberate: concurrent hardware decode is a per-device limit and some phones set it at one.
On iOS, play() only works from a user gesture, and an LFO- or MIDI-driven jump is not one. So every element is touched once — play then immediately pause — inside the gesture that loads the clips, which is what makes later automated switching work at all. If a slot ever refuses, the toast says to tap.
The two blocks at the right-hand end of the row set what a clip change does, whether you make it or the sequencer does. The first is the fade length — CUT, or 0.25 up to 4 seconds, tapping to cycle. The second appears once a length is set and picks how the two clips are mixed on the way across: normal is a straight crossfade, and the other nine blend modes are there because the composite reuses the same shader the gen chain does, so they cost nothing. difference and multiply between two clips are worth a try. A fade never outlasts the clips it is between: if either the outgoing or the incoming clip is shorter than the length set — a 3-second clip under a 4-second fade — that fade runs for the shorter clip's length instead. Left at 4 seconds it would still be crossing when the clip reached its out point, so the switch would land somewhere other than where the in and out points put it. Duration here means the in/out span at the clip's own speed, so a tighter in/out or a faster rate shortens the fade with it, and the block's tooltip names what a fade from the clip on screen would actually last. Both settings are part of the patch and travel in presets and share links, unlike the clips themselves.
During a fade both slots light in the row, because both are on screen. Both elements keep playing, which is what makes it a crossfade rather than a dissolve into a frozen frame — a clip that was reversing or ping-ponging runs forward for the length of the fade, because the stepper that drives those directions follows the active clip and the outgoing one would otherwise hold a single frame — and it is the only time two clips decode at once. Starting a fade while one is running finishes the first immediately rather than layering; a third element in flight is more than some phones will do.
Fade position is advanced from real elapsed time, not a frame count, so a 2-second fade takes two seconds whatever the frame rate is doing. The delta is capped at 100ms so a tab that was backgrounded resumes its fade instead of jumping to the end.
sequencerSAMPLER: the STEPS row under the CLIP row is an eight-step sequence of clip slots. Drag a clip block onto a step to fill it; drag a step onto another to swap them, or off the row to clear it. The same slot can fill any number of steps, so 1 1 2 1 3 is five steps using three clips.
The LIVE block can be dragged in too. A live step shows the camera, and since the camera has no in/out to end on it runs for a set length, shown on the step: L15s to start with. Tapping a live step cycles its length through 2, 4, 8, 15, 30 and 60 seconds; changing the one that is playing re-times it from that moment. A live step is always a cut in and out. The camera is asked for as the step is dropped, not at the first live step — a permission prompt belongs on the gesture that asked for it, not in the middle of a set — and is then held open while any live step is in the row, so it is not asked for again each time round. Clearing the last live step releases it. If permission is refused the step stays, and runs its length showing whatever is underneath. SEQ, on the RND row, starts it from the first filled step and stops it; tapping a clip step starts it there, or jumps a running sequence to it.
Each step plays its clip once across that slot's own in/out span, at its own speed and in its own direction, then hands over to the next filled step, wrapping after the eighth. Forward runs in to out, reverse out to in, and ping-pong one full round trip, in to out and back. The slot's loop setting is the one thing a step ignores — inside a sequence the sequence decides how long a clip holds the screen.
RND fills all eight steps from the loaded clips, never the same clip twice running and never the camera, so a random patch arrives with a sequence under it. It leaves the steps alone when no clip is loaded.
With a fade length set, a step hands over early by the length of the fade, so the fade runs across the tail of its span and the step still ends where its out point is. The lead is capped at 40% of the span so a short step is not all fade, and the fade itself is shortened to fit the shorter of the two clips. The same slot twice in a row is always a cut, because a fade needs two clips. A reversing or ping-ponging clip runs forward while it fades out, for the reason given under clip slots.
Steps name slots, not files: loading a new clip into slot 2 changes what every step naming 2 plays. A step whose slot is emptied is kept, drawn struck through, and skipped until the slot is filled again. The step lit in the row, and SEQn on the HUD status line, is the one playing.
Picking a clip by hand — a tap, shift+1 to 4, ; or ' — stops the sequence, as does tapping the LIVE block, opening or dropping a file over the playing clip, or leaving SAMPLER; the clip on screen carries on under its own loop setting. Editing the steps does not: a change lands at the next step end. PAUSE holds the sequence where it is.
The STEPS row and each live step's length are saved with a preset only when remember clip names & sequence is ticked in the SAVE dialog — the same tick that records the four clip slots, since steps name slots and are worth nothing without them. Without it, and in a share link either way, the sequence is session-local: a share URL carries no file names at all.
snapping slidersSome params are selectors rather than continuous values and snap to fixed positions as you drag: style on plasma, flowing-colours and zoom-clouds, sides on kaleidoscope, sectors on kaleido-warp, charset on ascii, mode on scatter, fall on flow-dots, and trail on feedback. The row shows the position number rather than a decimal, and the help entry for that shader lists what each one is.
A selector with only two positions is drawn as a toggle instead — a ☐ OFF / ☑ ON box in place of the bar, tapped rather than dragged. There are two: invert on ascii and 1-bit on bitcrush. They are ordinary params underneath, so they still take LFO, audio and MIDI modulation and still flip at the halfway mark
audio badgeEach param row has an audio badge (—/B/M/T/V). Tap to cycle: none → bass → mid → treble → volume. The selected band drives that param with audio level, at the depth and direction AUD AMT sets and scaled by that row’s influence
LFO badgeEach param row has an LFO badge (—/L1/L2/L3). Tap to assign an LFO to that param — cycles through LFOs then back to none. How much of it arrives is the influence number at the end of the row. Audio and LFO modulation add together
MIDI badgeEach param row also has a MIDI badge (—). Tap it to bind a CC — see the MIDI control section. MIDI sets the base value, then audio and LFO add on top of it
influenceThe number at the right of every parameter row, and the one control that answers "how much is this one actually moving". Drag it up and down: 0 to 100.
It scales every source at once — LFO, audio and MIDI together. At 100 each source does what its own controls say. At 50 everything reaching that parameter is halved. At 0 the slider is the value, whatever is still bound to it, so it is a per-parameter mute you can hold a patch under and let back in. One number rather than one per source, because that is the question you ask mid-set, and the answer has to mean the same thing whichever source the movement is coming from.
The cell is there on every row and keeps its width, dim until something is bound so the columns beside it never shuffle. Drag is vertical, which is what separates it from the row drag underneath — sideways sets the value, up and down sets how far anything may move it. About 120px of travel covers the whole range.
It replaces the old LFO TRIM slider and the M/F mode chip. A patch made before this opens with each parameter’s influence read off the trim it was saved with, so it moves as far as it did; a binding that used to sweep full range now moves around its slider like every other one
3 LFOsThree independent LFOs, each with shape, AMT and period. A parameter bound to one moves up and down around its own slider value, by AMT scaled by that parameter’s influence
shapesFive icon buttons: sine, triangle, ramp, square, and sample-and-hold (stepped random). The icons are drawn as vectors rather than text characters, so they render the same on every platform
SKWSkew — warps the waveform's timing without changing shape. At 0.50 the wave is symmetrical. It remaps the phase: whatever SKW reads is the fraction of the period the wave spends on its first half. Slide it up and a triangle's peak moves toward the end (becoming a ramp up), a square's duty cycle widens to match the setting, and a sine holds above its midpoint for that share of the cycle and snaps through the bottom — at 0.80 it is high for four fifths of every period. Slide it down for the mirror image. Works on every shape
CRVCurve. 0.5 is linear. Lower values stay near the centre and flick out to the peaks; higher values stay near the peaks.
previewThe mini waveform at the right of each LFO row is the swing a bound parameter takes on: the wave about a centre line, reaching AMT either side of it, with skew and curve applied. The centre line is the parameter’s slider. A negative AMT draws it the other way up. The fainter line is the OFS floor
AMTEach LFO’s own depth, on its row, from −1 to +1 with zero at the centre. It is the swing every parameter bound to that LFO gets, scaled by that parameter’s influence. A parameter travels AMT either side of its slider, so AMT 0.3 on a slider at 0.50 covers 0.20 to 0.80 and nothing outside it. Left of centre runs the wave the other way up over the same span. Dead centre holds everything on that LFO still — exactly still, at their sliders — without unbinding anything, which is the quickest way to take one oscillator out of a patch and put it back.
A slider near an end has less room on that side than the other, and the movement clamps there rather than wrapping: AMT 0.3 on a slider at 0.05 still reaches 0.35 but bottoms out at 0. Centre the slider to use the whole swing
OFSPhase offset, 0 to 1 of a cycle. Use it to offset LFOs that share a period; SYNC keeps the offset.
SEC modePeriod set in seconds (0.1s – 30s). Drag the period slider to adjust
BPM modeTap SEC to switch to BPM — period snaps to musical divisions of the global tempo: 1/8 · 1/4 · 1/2 · 1 · 2 · 4 · 8 · 16 beats
TAPTap repeatedly to set the global BPM — averages up to 8 taps, resets if gap exceeds 3 seconds
SYNCCopies LFO 1's period and mode (SEC or BPM) to LFOs 2 and 3, then resets all three phases to zero simultaneously — locks them to the same tempo and beat
assign to paramTap the LFO badge on any parameter row to cycle through L1 / L2 / L3 / none. A new binding moves around wherever that slider already sits, at whatever influence the row is on — 100 unless you have taken it down
yellow tickOn any parameter slider that something is moving — LFO, audio or MIDI — a yellow tick shows the value actually being drawn this frame, while the bar stays where you set it. Take the row’s influence to 0 and the tick goes: nothing is reaching it, and the bar is the value again
device pickerOnce enabled, select your MIDI controller from the dropdown — the dot turns green when connected. Works with any class-compliant USB or Bluetooth MIDI device
channelSet the MIDI channel to listen on (1–16) or All to receive from every channel. Useful when a device sends on a specific channel or when multiple devices share the same port
MIDI badgeEach parameter row has a MIDI badge (—). Tap it to enter learn mode (badge pulses yellow ●) — a popup appears where you can type a CC number (0–127), or N for note pitch, and press Enter, or just move a knob/fader or play a key on your controller to bind automatically
bound badgeShows the CC number (e.g. C7) when bound — the controller directly sets the parameter value. Tap again to clear and re-enter a new binding. Press Escape or click outside the popup to cancel
note pitchA row bound to N follows the last note played: C2 (36) is 0, C6 (84) is 1. The value holds after the key is released. Velocity is ignored.
stackingA bound CC sets the parameter outright once the controller has sent something, then the LFO and audio amounts add to that, and the result is kept inside 0–1. Influence scales the lot: at 50 a CC only pulls the parameter halfway from its slider toward the knob position, and the LFO and audio movement on top is halved with it
persistenceCC bindings are saved with presets and the share URL
Audio modulation
off / mic / vid / tab / fileSelect the audio source. mic is the microphone. vid taps the loaded clip's own soundtrack, so the visuals react to the footage rather than the room — it is an analysis tap only, the clip is never played to the speakers. It follows whichever clip is on screen, through jumps, loads and the sequencer, and during a crossfade it hears both clips at once. A clip with no soundtrack reads as silence. tab shares another browser tab and uses its audio.
file plays an audio file you supply — mp3, wav, ogg, m4a, flac, opus. Tap it to pick one, or drop the file anywhere on the window. Unlike vid this one is audible: it plays through its own element and the analyser taps the captured stream, so it is heard once, not twice. It loops, because a mod source that stops is a patch that stops moving. Tapping file while it is already running opens the picker again to swap the track. The HUD audio line and the export dialog both name the file rather than just saying “file”.
It records. Export audio set to source clones whatever the analyser is listening to, so the track that drove the visuals is the track on the finished video, in sync and with no second pass
tab audio, by browserOnly Chrome, Edge and Opera can do this. The picker has a Share tab audio checkbox that is not ticked by default, and without it you get a video track and no audio. Firefox and Safari implement the screen-share API but ignore the audio option entirely — no error, no checkbox, no audio track — so tab cannot work there at all and the toast says so. Use mic or vid instead on those browsers
if a source will not startThe toast names the reason and the console carries the full error, the sample rate the context settled on and the track's own settings. Two causes account for most of it. A browser remembers a permission answer, so a second attempt shows no prompt at all — a mic that was blocked or dismissed once fails instantly and silently, and has to be re-allowed from the padlock in the address bar. And Firefox will not resample between a capture stream and an AudioContext: where the two run at different rates it refuses outright rather than converting, while Chrome and Safari convert without comment. The audio engine negotiates the rate against the track and retries, so this should no longer bite, but it is what a sample-rate mismatch toast means
audio suspendedBrowsers start an AudioContext suspended unless it is created during a click, and a permission prompt can sit open long enough that the click stops counting. A suspended context runs nothing, so the meters sit flat with no error anywhere. The AUDIO line in the panel turns amber and reads suspended when this happens, and the next tap or keypress anywhere starts it
vid, by browser and by transportNeeds captureStream on the video element, which Safari and iOS do not have. It also only produces audio while the element is actually playing: reverse and ping-pong drive the playhead by hand with the element paused, so the meters flatline on any reverse pass. It follows the clip on screen by itself — through jumps, shift+N, loads and the sequencer — and during a crossfade it hears both clips, so the sound crosses with the picture; there is no need to reselect vid after changing clip. A clip with no audio track reads as silence rather than as a fault. Screen capture cannot feed it, since that path binds a stream rather than a file
nothing is movingThe status line above the meters names the source, and adds (suspended) when the browser has an audio context open but not running — tap anywhere and it will start. If a source fails, the toast names the reason rather than a bare error code: denied permission, no device, device busy, or a sample-rate mismatch. The console carries the sample rate and context state for every successful start
BASS / MID / TRE / VOLThe four modulation signals, not raw levels. Each band is measured as real energy, follows hits with a 5 ms attack and the RELEASE time, and is scaled between its own recent quietest and loudest (about the last four seconds), so it swings the full range whether the input is a quiet mic or a hot line. A steady tone therefore reads near zero after a few seconds: these follow movement. Below about −72 dB a band fades to zero. VOL is overall loudness. BASS is 20–250 Hz, MID 250 Hz–4 kHz, TRE 4–16 kHz. The mic is opened with echo cancellation, noise suppression and auto gain off, since all three damage music
AUD AMTHow far the selected parameter’s band moves it, from −1 to +1. This one sets the DIRECTION as well as the depth — right of centre pushes the parameter up on each hit, left pushes it down — which is why it is still its own control rather than folded into influence. The slider value is where the parameter rests in silence. Influence then scales whatever this asks for, so ±0.50 at influence 100 is a strong, clearly visible movement and the same setting at influence 25 is a quarter of it
RELEASEHow long a band takes to fall back after a hit, 10 ms to 4 s on a log scale; about 150 ms is the default. Short gives strobing, long gives swells. One setting for all four bands. Presets saved before this build stored a HOLD value here and load it as a release time; HOLD at 100% used to freeze the level, and now gives the longest release
on the projectionThe output window draws exactly the parameter values the control window computes each frame, including audio, LFO and MIDI movement, and it is sent the spectrum and waveform for the shaders that draw them. The two screens cannot drift apart, and the output window needs no audio or MIDI of its own
Blend modes — per-shader compositing
stack orderIn SAMPLER and LIVE modes, the video/camera sits as the base layer. Each GEN shader composites on top of it in chain order
blend rowWhen a GEN shader is selected, a BLEND row appears at the top of its params. Drag it to set how much that shader mixes onto the layer below it
mode labelTap the mode label in the blend row to cycle through compositing modes: normal · add · screen · multiply · difference · lighten · darken · overlay · dodge · burn
FX blend rowFX slots have the same two rows, but they mix the effect against its own input rather than against the layer below. The full list of modes is identical
normal vs the restnormal at mix 1.00 is a plain serial effect — nothing is composited, so it costs nothing extra. Any other mode always runs a compositing pass, even at mix 1.00
◉ CAMTap the camera block on the top row, just right of SRC, to turn the live camera on/off directly. In LIVE mode the camera is the base layer; in SAMPLER the base is the selected clip, or the camera when the fifth CLIP block is lit.
Four things can claim the camera: LIVE mode, the fifth CLIP block, a SHADER blend running against the live source, and a live step sitting in the sequencer's STEPS row — that last one from the moment the step is dropped, whether the sequence is running or not, which is why the light comes on as you build the sequence rather than when it first reaches the step. Dropping the last of them does not stop the stream immediately — it is held for about eight seconds, and anything that asks in that window reuses it. That is not a cosmetic delay: reacquiring means a second permission request, which Chrome answers from the stored grant but Safari and any file:// copy cannot, so you would be asked again for a camera you had just allowed. Once nothing claims it the tracks stop on the timer and the light goes out. The timer re-checks on the way out, so taking a fresh claim inside that window keeps the camera rather than losing it when the eight seconds are up
Source section
appears automaticallyA permanent row of source controls appears just below the header buttons whenever the camera is on, or LIVE or SAMPLER mode is selected — no need to open anything
SAMPLER transportA row of icon buttons matching the SRC row: play/pause (the icon shows what tapping will do, and the caption follows it), reverse — which works the same way, playing backwards and then pausing, with the play button being how you return to forwards — restart to the in-point, open a file, loop, and ping-pong. Each lights when active, and only one direction can be lit at a time. Speed sits on its own row as text pills, and the in/out slider gets a full row to itself since it needs the width.
Every button in the section is one cell of a fixed 46px grid, so the transform row lines up block-for-block under the transport row above it and the leftover space stays at the right — which is where anything added later goes. Captions are clipped to their cell. They used to be 7px text in a 30px box free to overflow it, and 7px is below the size any browser guarantees to honour: a minimum-font-size setting or mobile text autosizing rendered them at 11 or 12px while the box stayed 30px wide, and neighbouring captions ran into each other.
SPEED and IN / OUT are the same control drawn twice: label on the left, a 3px track across the rest of the row, and the value in a shared right-hand column. Speed has no 1× button any more — double-click the slider. On the in/out track the two markers are the in and out points and the cyan tick is the playhead, standing above and below the track rather than inside it. The number is the length of the range; the in and out clock times are on its tooltip. Each marker carries an invisible touch box about four times its width, so what you drag is finger-sized while what you look at is not a slab of green
play from a dead spotIf the playhead is outside the in/out range — which is where dragging the out handle leaves it — play snaps back to the in-point instead of resuming into a dead spot and stopping again. Pausing and playing anywhere inside the range resumes where you left off; restart always jumps to the in-point
SAMPLER: restartJumps back to the in-point (or the start) and plays forward from there
SAMPLER: open file…Same as the O key / open file button elsewhere — opens the file picker dialog to load a video
SAMPLER: SPEEDA continuous slider from ¼× to 4×, log-mapped so 1× sits dead centre and every doubling covers the same distance. It has soft detents — land within a hair of ¼ ⅓ ½ ¾ 1 1¼ 1½ 2 3 4 and it grabs the round number, otherwise you keep whatever you dragged to, shown to two decimals beside it. Double-click the slider to snap straight back to 1× — the button that used to do it has gone, and the row is the better for the width. Applies to forward playback and to reverse/ping-pong stepping, and carries over when a new file is loaded
SAMPLER: LOOPOn (default): restart at the in-point (or the start) once the out-point (or the end) is reached. Off: playback stops there instead of restarting
SAMPLER: PING-PONGBounce direction at each boundary instead of restarting — plays forward to the out-point, then reverses to the in-point, and repeats. Overrides LOOP while enabled
IN / OUT previewDragging a handle parks the playhead on it — the in handle shows the frame you are starting from, the out handle the frame you are ending on — so you can set points by eye. Playback holds still while you drag and picks up again when you let go
SAMPLER: IN / OUTA slider spanning the whole clip. Drag the left handle to set the in-point and the right handle to set the out-point — playback loops (or ping-pongs) between them, and the cyan bar shows the live playhead. Drag a handle fully to the start/end to unset it; clr resets both. Stays in sync with the 0-key in/out method
SRC iconsTwo tight groups with a gap between them: camera on/off plus front / rear facing (a face in a frame for the selfie camera, a landscape for the rear), then rotate, flip and mirror. The camera group appears in LIVE, whenever the camera is running, and in SAMPLER while the fifth CLIP block is lit — wherever the camera is the picture, front/rear has to be reachable. In SAMPLER with that block lit the camera icon turns it back off rather than jumping to LIVE mode. Each icon lights when active and rotate shows its angle. In LIVE the camera icon stays lit and does nothing when tapped; the L key still toggles LIVE from the keyboard
FACINGSwitch between front and rear camera. On a device with no coarse pointer the two buttons are dimmed and inert rather than hidden — the row keeps its layout, so nothing shifts when you move between a phone and a desktop. facingMode is a preference and not a guarantee: the app records which camera it actually got, not which one it asked for
rotate / flip / mirrorThe last three icons in the SRC row: rotate the source 90° at a time (the icon shows the current angle), flip it vertically, mirror it horizontally. Each lights when active
BLEND rowOnly appears in SHADER mode, since that is the only mode that composites generated output against footage. The two overlapping circles mark the row; the two icons pick what it blends against — a play symbol for the loaded video, a camera for the live camera. The on/off button toggles the blend, and the text beside it shows the current mode and amount, which are set from the BLEND row in the params above
blend toggleThe rightmost icon in the SRC row, marked blend. One switch: either the source plays straight through, or the whole generative stack is composited over it. It only appears in SAMPLER and LIVE, the two modes that bypass the gen chain by default so the shaders do not cover the footage; SHADER bypasses nothing, so it is not needed there. For per-slot control, double-click blocks in the flow strip instead. It starts off in two places — arriving in SHADER, and loading a clip — so neither lands half-mixed with whatever was there before. A preset keeps whatever it saved: loading one does not route through the mode switch, and locating a preset's missing clip restores the saved setting after the load.
Export video
recordSits with flip V and rot 90° in the VIDEO section. Everything a take needs is asked for when you press it, so there is nothing to set up first. While a take runs the button becomes the progress bar — it fills left to right and reads elapsed, total and percentage, so you can see how far in you are without leaving the output. Tap it again to stop early; the file keeps whatever was recorded
export sizePins the render buffer to an exact size for the take, ignoring window size, device pixel ratio, RES and RENDER CAP.
The preview changes when a take starts, and both changes are the point rather than faults. The frame takes the export's shape, letterboxed inside the window, so what is on screen is framed the way the file is. And the picture goes to the export's resolution, because captureStream reads the canvas backing store and that store has to be the file. On a display bigger than the export — a 4K panel recording 1080p, say — the preview is upscaled for the duration and looks softer than it did a second earlier. That is the file's real resolution on screen, not something the take did to it. Exporting at a larger size is the only thing that changes it: the canvas is pinned to the export size under all three framing modes, so the preview looks the same in each and reframe does not help here. 720p, 1080p and 4K in the screen group; 1080×1920 vertical, 1080×1350 feed, 1080×1080 square and 1920×1080 wide in the social group; or as displayed for the old behaviour. While a sized take runs the preview letterboxes to that shape, so you are composing against the framing that will be in the file rather than your window’s
framingWhat happens when the size you picked is not the shape the preview is running at. fit is the default and the only one that loses nothing: the whole frame goes in, with bars where the shapes differ, and the file is a resample of exactly what was on screen. fill fills the frame and crops the overflow — usually what a feed post wants. reframe re-renders the chain at the target shape instead, which is right when the take is the composition: a 9:16 set built and watched in a 9:16 window renders 9:16 natively and comes out sharper for it.
Worth being exact about what each one renders at. All three render big and scale down. The buffer is sized to two floors at once: large enough to cover the export on both axes, and holding at least as many pixels as the preview was composing with. The second floor is the one that matters on a large display, where the file is usually smaller than the window — without it a take drops to the file's pixel count and every grid-based effect lands proportionally larger, which looks like a zoom. fit and fill draw at the preview's shape; reframe draws at the export's shape, at the same pixel count. From a 16:9 preview running a 2560×1440 buffer, a 1080×1920 export renders 3413×1920 under fit or fill and 1440×2560 under reframe — both larger than the file, both downsampled into it. Reframe changes the framing; the other two do not.
Why fit and fill do not simply re-render: every effect built on a grid or a fixed pixel size — bitcrush, ascii, halftone, flow-dots, grain — keeps its cell size in absolute pixels while the frame changes shape, so those cells grow or shrink relative to the frame when the aspect changes. That reads as a zoom rather than a crop. Under fit and fill the chain draws at the preview's shape and that image is mapped into the file, so nothing in the chain has to know the export is happening. Reframe does change the shape, deliberately, but holds the pixel count — cells per frame is an area relationship, so equal area is the same cell size relative to the frame whatever the aspect does.
The estimate line says what each choice will cost before you commit — how much of the frame goes to bars, or how much gets cropped off which edge. It also names the render buffer when it is larger than the file, which under fill it usually is: a 4K fill from a 9:16 preview wants 3840×6827, about 26 megapixels a buffer. RENDER CAP is deliberately ignored here, because it exists to protect interactive frame rate and a take is not interactive — inheriting it would force the upscale this whole path exists to avoid
will it keep upThe estimate line predicts the frame rate a take will hold, and warns when it will not. The number comes from ordinary use rather than from a benchmark: the app divides the frame time it is already measuring by the work it already knows about — buffer size times the number of passes the live chain runs — which gives milliseconds per megapixel-pass on this device, at its current temperature, with this chain loaded. It re-learns continuously, so a phone that has warmed up predicts lower than the same phone did cold.
This matters because captureStream never drops frames, it repeats the last one. A take the device cannot keep up with does not come out short; it comes out exactly the right length with stuttered motion, and nothing about the file says so afterwards. The warning before you record is the only notice you get.
The prediction extrapolates linearly from the size currently being rendered, which holds while the GPU is fragment-bound and breaks once a large buffer crosses a memory-bandwidth limit — so it is optimistic exactly where a phone falls over. That is why the memory ceiling beside it is plain arithmetic and not measured: whether a take allocates is a multiply, and it stays answerable on a device whose capability strings cannot be trusted. Both numbers are on the I overlay.
export qualitydraft 5, good 10, high 25 or max 50 Mbps. A single rate cannot serve every size — 8 Mbps is generous at 720p and starved at 4K — so it is picked per take. The line under the fields gives the buffer size, the frame rate and the estimated file size, and warns when the bitrate is thin for the size selected
export lengthSeconds, 1 to 120, typed rather than dragged. The estimate updates as you type; two minutes of 4K at max is about 750 MB. The completion dialog names the length actually recorded next to the filename, so a file whose timeline disagrees with its footage is visible without opening it
export audioThree settings, defaulting to off: no take opens a microphone unasked. source records the audio input already running — mic, tab or the loaded video’s own track — which is the same signal the visuals are reacting to, so picture and sound line up in the file. It is selectable only while an input is running; with AUDIO off the option is greyed and names why. mic opens a microphone for the take alone, with echo cancellation, noise suppression and auto gain all turned off, since those three defaults suit speech rather than music. Use it to record the room over a set running on tab audio or on nothing
audio and the filePicking a source switches the container to a codec pair that carries audio: avc1+aac for mp4, vp9+opus for webm. Audio rides at 256 kbps and is left out of the size estimate, being about 32 kB a second — under 3% of the video track.
Every capture asks for unprocessed stereo at 48k, with echo cancellation, noise suppression and auto gain all off. Those three are on by default in a browser audio capture and all three are wrong for music: echo cancellation subtracts a delayed estimate of the signal from itself, which on anything but speech is a sweeping comb filter — the phasing, underwater sound. Noise suppression eats sustained tones and cymbals, and auto gain rides the level. Constraints are requests the browser may narrow, so the recording toast names what the track actually settled on: a capture that came back mono at 16k is worth knowing about before the take rather than after listening to it. If the mic is refused or the source has stopped, the take still runs — silent, with a toast naming the reason
record btnOpens filename dialog — enter a name and tap record. Button counts down; tap again to stop early
save dialogTap SAVE to trigger the platform save/share sheet (iOS: Files or AirDrop; desktop: choose location). Tap DISCARD to delete
formatSaves as mp4 where supported, webm otherwise — both can be reloaded as SAMPLER sources
iOS tipIf the save sheet doesn't appear, use iOS Screen Recording (swipe to Control Centre, tap record) to capture the full screen
snap pngA single frame, written as a PNG. Sits next to capture screen in the VIDEO section; that one brings a screen in as a source, this writes the output out. F9 is the keyboard equivalent. It uses the same EXPORT SIZE as a recording, so a snap at 4K is 4K regardless of window size: the buffer is resized, held three frames while the render targets settle, read, then handed back. Two limits — resizing clears the feedback history, so a snap of a long trail catches it three frames old, and a snap is refused while a take is recording, since resizing under a running capture would corrupt the rest of the file
Projection / dual screen (CAST)
CAST buttonOpens a second browser window showing only the canvas — no controls, no locate bar, black background, and no text of any kind: the toast messages, the perf meter, the system info panel and the help overlay are all suppressed there, so a shader change or a numpad press from the controls never writes green text across the projection. Use on a projector or second screen; in Chrome it opens on the other screen by itself. Click it once to fill that screen — see fullscreen below
● CAST indicatorPulses cyan when an output window is connected. All param changes, shader switches, LFO and audio sync automatically via BroadcastChannel
fullscreenFullscreen always takes the screen the window itself is on, so the output window has to be ON the second screen before it fills it. There are two ways to fill it, and on macOS they are not the same thing.
Click the output window to size it to the screen it is on. It stays an ordinary window, so everything on your other display stays exactly where it is. The browser's title bar stays too — about 28px across the top. M does the same from the keyboard.
F is true fullscreen, which is the only way to be rid of that bar. On macOS it also hands the window a Space of its own, and unless Displays have separate Spaces is turned on in System Settings → Desktop & Dock → Mission Control, every other display goes black for the duration — the controls vanish until you leave fullscreen. That setting needs a log out and back in to take effect, and it is the fix if you want a borderless output. It is a system setting; no page can opt out of it, which is why a click fills the screen rather than going fullscreen. F again leaves.
In Chrome and Edge, CAST asks for permission to see your screen layout the first time, then opens the output window on the screen the controls are not on, sized to it. On Windows and Linux it opens fullscreen there as well; on macOS it is sized rather than fullscreen, for the reason above. With three or more screens, pressing CAST again walks the output on to the next one. In Safari and Firefox no page can know a second screen exists, so the window opens where the browser puts it and the line at the bottom says to drag it across first. The pointer hides itself after two still seconds
SAMPLER / LIVEThe output window cannot share the control window's video or camera — load the same file (O key or drag) or start the camera (L) separately in the output window
same machine onlyBroadcastChannel works within the same browser on the same device only
Diagnostics
P — perf meterTop-left overlay, also on the MISC row. Frame rate and mean frame time over a rolling second, the worst single frame in that second (peak), how many frames missed their deadline (late), the internal buffer size, the source texture size, an estimate of resident GPU memory, and how many non-bypassed GEN and FX slots are running. The figure turns amber past 16.8 ms and red past 33.3 ms — absolute thresholds, because the question is always whether it is holding 60
mean vs peakBoth are shown because either alone lies. A 90 ms hitch once a second still averages out near 60 fps, and a mean that looks fine next to a peak that does not is exactly what a visible stutter is
I — system infoTop-right overlay. GPU renderer and vendor, the translation backend (native, or which ANGLE flavour), shader precision, texture limits, float render-target support, device pixel ratio, screen and buffer size, cap and scale settings, and the loaded source. COPY puts the lot on the clipboard — the fastest way to answer “it runs slower on my machine”
mediump lineThe one worth understanding. 10 bits means the GPU runs mediump as true fp16, which is roughly twice the arithmetic throughput; 23 bits means it is promoted to fp32. Apple Silicon gives the former, Windows through ANGLE the latter — the same shaders, a real speed difference, and not something either machine reports on its own
source lineResolution, duration, estimated frame rate and file size of the loaded clip, also reported to the console on load. RENDER CAP does not bound this: the source texture is whatever the file is, and it is re-uploaded every frame. A clip wider than the GPU's texture limit cannot upload at all and now says so instead of showing black
Save / Load / Share
SAVEStore the full current state as a named preset in the browser — shader chain, FX chain, all params, LFO config, blend settings. The name is filled in for you as time, then date, then the word preset — 1432-12aug-preset. A block on the strip is only about ten characters wide, so leading with the time is what makes one save tell itself apart from the next at a glance; the trailing word is cut off there but still reads in this list. Type over it with anything you like
LOADRestore a saved preset — lists all stored presets with timestamps
SHAREGenerate a compact URL with all settings encoded — all per-slot parameters, FX blend modes and mix amounts, chain order, LFO/audio/MIDI modulation are preserved. Bookmark or share to reload exact state on any device (video file not included). A real link is a few hundred bytes; anything claiming to be far larger is refused rather than opened, so a malformed or hostile link fails with a message instead of locking up the tab.
Links written by older releases still open: version 4 and 5 are read as well as the current format, which is the only one written. A link from before this build opens with each LFO’s AMT positive and each parameter’s influence read off the per-binding depth it was saved with, and a link written now opens in an older build with influence read back as that same per-binding depth rather than refused. Older than that will not open, and that is deliberate rather than an oversight — those links index a shader table that has since changed size, so decoding one would quietly name the wrong shaders instead of failing. A link that opens as somebody else's patch is worse than a link that says it cannot be read
unplayable filesA file the browser cannot decode now says why — format unsupported, decode failed, network error or aborted — instead of leaving loading… up forever. Codec support is checked before the load starts, not after it fails
RSTReset all shader and FX parameters to defaults, keeping the current chain
EXPORT BANKIn the SAVE dialog, in its own block under the preset name — writing the bank out is a save, the same as writing one preset. Name the file in the box beside the button; it is filled in with the date and you can type over it. Anything a filesystem would object to is replaced with a dash, and the toast names the file it actually wrote. Writes every saved preset to a single .json you can copy onto a flash drive next to index.html, mail to someone, or keep in version control. The video files themselves are not included
IMPORT BANKIn the LOAD dialog — or just drag the .json onto the window. Loads a bank file back. It merges: presets already here are kept, and re-importing the same file adds nothing. Nothing a bank file can contain will overwrite what you already have
bank autoloadA file named recur-bank.js in the same folder as this page is added to the bank when it opens. EXPORT AUTOLOAD in the SAVE dialog creates it; move it next to this page, replacing any older one. It only adds presets: ones already in the bank are skipped, and presets you have deleted or overwritten are not brought back. Each version of the file is merged once per copy of the page.
CLEANIn the LOAD dialog. Where several presets share a name (an overwrite merged back from an older bank file, or the same bank imported twice) it keeps the newest and removes the older ones, after asking with the count. Presets with different names are never touched. Removed presets are not brought back by an autoload file.
presets and footageA preset saved in SAMPLER records which clip it was built on — filename, size and length — and its in / out points, but not the file itself. Load one whose clip is not open and a bar appears naming the file, with LOCATE to point at it. The shaders load instantly either way; the bar never blocks a jump.
Tick remember clip names & sequence in the SAVE dialog and the preset carries all four clip slots instead of one — each slot's file name, in / out points, speed, loop and direction — along with the STEPS row and the length of each live step. Loading it asks for everything missing at once: LOCATE takes a multiple selection, and FOLDER takes the folder the clips are in and binds every match in it, so a four-clip set is one pick. Matching is by file name, then by size where two files share a name; a re-encode under the same name is accepted and a single hand-picked file is taken at face value for the clip being asked for. Whatever is found lands in its own slot, so the sequence plays as saved. The setting is remembered between saves, and the row is greyed out when no clip is loaded. Without it a preset behaves as it always has and carries no file names at all
locate onceA located file is remembered for the rest of the session, so a bank of presets built on the same clip only ever asks once, and a second preset naming the same footage binds without a prompt. SKIP silences every file the bar is asking for until you reload — stepping through presets for footage you did not bring stays quiet
in / out pointsSaved with the preset and restored once the clip is bound, clamped to its actual length. A preset with no clip attached leaves your loop points alone
why presets don't travelSaved presets live in browser storage, which belongs to the browser profile, not to index.html. Copying the file to a flash drive copies none of them, and opening it from the drive may find a different set entirely. The bank file is how they move
preset storagePresets live in browser storage, which is capped at a few megabytes. If it fills, saving says so rather than failing quietly — and no longer claims to have saved. Delete a few from the LOAD list to make room. Private-browsing windows may refuse to store anything at all
DEFRevert to initial state — clears the FX chain, resets the GEN chain to a single shader with default params, and clears all blend and mod settings
Keyboard shortcuts
ENTERCycle mode: SAMPLER → SHADER → LIVE. SAMPLER and LIVE arrive with the GEN chain bypassed so the source shows through; SHADER arrives with it restored
FToggle fullscreen
LToggle camera
OOpen video file
SPACEPlay / pause (SAMPLER)
RPlay backwards, or pause if already reversing (SAMPLER). Press SPACE to go forwards again
0SAMPLER/LIVE: in → out → clear. SHADER: cycle selected gen. Has a button in the VIDEO section whose caption changes with the mode, so the current job is named on it
4 – 9SHADER: toggle gen shaders 1–6
− / +Toggle previous / next FX slot
/Clear the entire FX chain (same as the fx off button) — works the same in every mode
*Toggle next FX slot — same binding as +
.Toggle feedback trail
1 / 2 / 3Next param · decrease · increase
[ ]Previous / next preset in the bank
; 'SAMPLER: previous / next LOADED clip. The pair next to [ and ], which step the preset bank — same gesture, adjacent keys, different bank. Empty slots are skipped, and stepping off the live camera lands on a clip
shift 1–4SAMPLER: jump straight to clip slot 1–4. Shifted because the bare digits are param and gen-slot controls, and a clip jump reloads the source
shift 5SAMPLER: toggle the live camera in and out of the source position — the fifth CLIP block. Carries on the row where the four clips leave off
BKSPSwitch param layer: gen ↔ fx
F9Snap a PNG of the output at the export size. A function key rather than a letter: the letter keys are all live controls
ESCCloses the NEW dialog, and cancels an armed OVR or CLR. Does nothing otherwise — it is not a general escape, and it will not close this screen
?Show / hide this help screen
click to fill this screen · F for true fullscreen
CC
WebGL2 not supported in this browser.
RECORDING COMPLETE
Camera Access
On most browsers: click the camera icon in the address bar, set to Allow, then reload.
Save Preset
⚠ Video files are not saved — only shader settings and parameters.
Bank — every saved preset in one file
New Patch
Save the current patch as a preset first?
Chains, params, modulation, LFOs and tempo go back to their defaults. Clips, camera, mode and playback settings stay as they are.
Load Preset
Share Link
All current settings are embedded in this URL. Video files are not included.