huff opens two windows. The controls window is your workspace. The canvas window is the fullscreen output that receives processed frames over the embedded WebSocket relay.
Controls are organised into collapsible groups. Click a group label to collapse or expand it. Collapsing a group does not disable its effects — use the ON toggle inside each group for that.
Top Bar
| Control | Description |
| File | Load a video file. Drag-and-drop also works. MP4, MOV, WebM, and any format your system decoder handles. |
| ▶ Play / ⏸ Pause | Toggle video playback. Resuming after pause restarts the frame pump automatically. |
| VOL | Output volume. Routed through a dedicated Web Audio AudioContext + GainNode so audio playback runs on its own thread and does not drop out under heavy canvas load. Drag to zero to mute. |
| RATE | Playback speed: 0.25×, 0.5×, 1×, 2×, 4×. Applies immediately without reloading. |
| LOOP | Loop the file continuously. Unchecking plays once and stops. |
| ↻ Refresh | Re-seed glitch randomisation. |
| ↺ Reset | Reset all parameters to defaults. |
| CLR BUF | Instantly wipes the frame ring and all internal buffers (gBuf and the shared gScratch ping-pong buffer) and resets cluster physics. Use this to clear accumulated trails/feedback/glitch history without resetting any parameter values or noise phases — the animation continues from where it was. |
| Camera | Select a webcam from the dropdown. Click ↻ Refresh to scan for newly connected devices. |
| Seek Bar | Scrub to any position in the loaded file. Uses fast keyframe seeking while dragging for low latency; playback resumes automatically on release. |
| Time Display | Shows current position and total duration as M:SS / M:SS. |
Source Group
| Control | Description |
| BASE VIDEO | Show the raw source frame underneath the glitch output. |
| BASE MIX | Opacity of the base video layer at final composite. 0 = fully glitched output, 1 = raw source on top. |
| BASE BG | Background fill colour when no tile covers a pixel: Black, Green (chroma key), Blue, or White. |
| SEED ON LOAD | Randomise the seed each time a new file is loaded, giving every clip a visually distinct glitch pattern. |
| SEED | Randomisation seed. Same seed + parameters = same output. |
| QUALITY | Scales the frame ring depth (0 → 4 frames, 1 → 60 frames). The single most impactful performance lever. |
Feedback Group
| Control | Range | Description |
| FEEDBACK | 0–3 | Contribution of the previous frame. Values > 1 over-expose. |
| PERSISTENCE | 0–10 | Decay rate between frames. Higher = trails linger longer. |
| FB X | -1–1 | Horizontal translation per frame. Creates lateral drift. |
| FB Y | -1–1 | Vertical translation per frame. |
| FB Z | 0.98–1.03 | Zoom per frame. < 1 = implode inward. > 1 = explode outward. |
| FB θ | -2–2 | Rotation in degrees per frame. Creates spinning feedback tunnels. |
| ↺ Reset Motion | button | Returns FB X/Y/Z/θ to neutral (0, 0, 1.0, 0). |
FEEDBACK above ~2.5 combined with non-neutral FB Z can saturate the buffer (full white or full black) within seconds. Recovery: lower FEEDBACK to 0, click ↺ Reset Motion, or use CLR BUF in the top bar to wipe the buffer instantly.
Glitch Group
The core datamosh engine. Reads tiles from past frames and blits them onto the current frame at noise-driven positions.
| Control | Range | Description |
| ON | toggle | Enable/disable the glitch pass entirely. |
| DEPTH | 0–0.5 | How far back in the ring tiles are sampled. |
| SCATTER | 0–1 | Per-tile randomisation of the lookback index. |
| CORRUPT % | 0–7 | Fraction of grid tiles displaced per frame. 0 = nothing moves. 7 = every tile replaced. |
| DRIFT | 0–1 | Noise-driven oscillation of corruption density. The percentage breathes slowly when > 0. |
| PIXEL SIZE | 150–2000 | Tile size in pixels. Larger = blockier datamosh. Smaller = fine grain displacement. |
| GLITCH SIZE | 1–60 | Spatial scaling of each tile relative to PIXEL SIZE. |
| OPACITY | 0–1 | Alpha of each blit tile. Also scaled by the A/B Mix layer-priority weight. |
| JITTER | 0–1 | Magnitude of per-tile position noise. |
| SMEAR | 0–200 | Duplicate stamps trailed behind each tile. |
| SMEAR ANGLE | 0–360 | Direction of the smear trail. 0 = noise-driven per frame. |
| SPEED | 0–5 | Phase velocity of the noise field driving tile selection. |
| FINE | 0–10 | Secondary fine speed multiplier. |
| MULT | 0–10 | Overall speed multiplier. |
| GLITCH X / Y | -1000–1000 | Base offset applied to all tile destination positions. |
Clusters Group
Locked directly beneath Glitch as part of the same conceptual unit. Biases glitch tile placement toward moving focal points (cluster centres) rather than scattering tiles randomly. Glitch must also be ON. Each centre has its own physics simulation with inertia, steering, and optional velocity bursts. Centres always use the physics simulation — even at SPEED 0, where the desired velocity is zero and centres glide to a stop and hold position (no per-frame re-randomisation).
| Control | Range | Description |
| ON | toggle | Enable cluster-biased tile placement. Glitch must also be ON. |
| CENTERS | 1–20 | Number of cluster centres. Each is an independent physics body that tiles gravitate toward. |
| SPREAD | 1–300 | Radius in pixels around each centre within which tiles are distributed. |
| MIN RAD | 0–150 | Minimum distance from centre — creates a hollow ring of tiles. |
| SPATIAL GAP | 0–200 | Minimum pixel distance between any two tiles. Prevents overlap. |
| BIAS | 0–1 | Fraction of tiles forced into clusters. Remainder placed randomly across the canvas. |
| DRIFT | 0–5 | Adds noise-driven wandering to centre positions. |
| SPEED | 0–10 | Speed of cluster centre physics simulation, step 0.01 for fine low-end control. 0 = centres glide to a stop and hold still. |
| SPD VAR | 0–2 | Per-centre speed variation. Each centre gets its own speed multiplier so they move at different rates. 0 = all same speed. |
| PULSE | 0–10 | Periodic velocity kick — centres suddenly burst in a random direction then settle. Higher = more frequent bursts. |
| INERTIA | 0.01–0.99 | Momentum of cluster centres. High = smooth gliding. Low = snappy response to steering. |
Layer Priority Group
A deliberately stable binary paint-order control between the Corrupt/Luma group and Scanlines. Pass 48 removes the old frame-alternating and pulse-order modes because they behaved like temporal flicker rather than meaningful layer hierarchy.
| Control | Options | Description |
| PRIORITY | SCAN TOP / CORRUPT TOP | SCAN TOP draws Scanlines last. CORRUPT TOP draws the Corrupt/Luma group last. Both are stable until explicitly changed. |
Luma Key Group
A luminance-derived key with explicit target, key source, Clip/Gain-style shaping, stored stencil memory and keyed-fill compositing. X-FADE and SOFT ADD retain the INDIGO-inspired pair; Pass 48 adds a small set of HUFF Classic blend fades over the same keyed patch.
| Control | Range / Options | Description |
| ON | toggle | Enable the Luma Key. |
| TARGET | COMPOSITE / CORRUPT / SCAN | Choose whether the key restores clean imagery over the composite or directly gates Corrupt / Scan objects. |
| DARK ↔ BRIGHT | 0–1 | Clip / luminance threshold. |
| GAIN | 0.25–4 | Controls key edge steepness. |
| MIX | 0–1 | Overall key opacity. |
| INVERT | toggle | Invert the key signal. |
| KEY SRC | LIVE / STENCIL | LIVE follows incoming luminance. STENCIL uses the captured internal luminance plane. |
| STENCIL | CAPTURE | Capture bounded luminance memory for later keying. |
| FADE | X-FADE / SOFT ADD / LIGHTEN / DARKEN / MULTIPLY / OVERLAY / HARD LIGHT / DIFFERENCE | COMPOSITE-target keyed-fill relationship. The first two preserve the existing behavior; the additional modes are HUFF Classic extensions using the same matte and keyed patch. |
| CLEANUP | 0–1 | Suppress low-level key leakage. |
| DENSITY | 0–1 | Push strong key regions toward full opacity. |
Buffer Trails Group
| Control | Range | Description |
| ON | toggle | Enable/disable. |
| TRAIL LAYERS | 0–4 | Number of ghost frames composited. |
| TRAIL DEPTH | 0–1 | How far back in the ring to pull trail frames from. |
| LUMA KEY | 0–1 | Drops dark pixels from trail frames. Only bright areas trail. |
Symmetry Group
| Control | Options | Description |
| ON | toggle | Enable/disable. |
| MODE | vertical / horizontal / both | Vertical mirror, horizontal mirror, or both axes. |
| SYM POS | 0–1 | Position of the mirror axis. 0.5 = centred. |
Scanlines Group
Displaces bands of the current video frame spatially — no temporal sampling from the ring. Bands shift the current content perpendicular to their axis; they do not pull from historical frames, so they stay smooth and follow live motion with no buffer-trail artifact. The whole band pattern can be rotated to any angle, including continuous spin.
| Control | Range | Description |
| ON | toggle | Enable/disable. |
| ANGLE | -180°–180°, step 0.5° | Rotates the entire band pattern. 0° = horizontal bands displaced left/right. 90°/-90° = vertical bands displaced up/down. Any other value = diagonal bands. The band span and displacement axis are recalculated for the full rotated canvas so bands always cover the whole frame and stay centred, at any angle. |
| 0° / -90° / 90° buttons | buttons | Snap ANGLE directly to 0°, -90°, or 90°. Because the slider spans 360° in a small space, landing exactly on these values by dragging is impractical — these buttons jump to them instantly and update the label. |
| SPIN L / SPIN R | toggles | Continuously rotate the band pattern left (counter-clockwise) or right (clockwise) instead of holding a static ANGLE. If both are somehow active, SPIN R takes priority. While neither is checked, the internal spin position stays in sync with the ANGLE slider so enabling spin starts from the slider's current angle with no jump. |
| SPIN SPD | 0.1–10 | Spin speed. At 1.0 the pattern completes a full rotation in roughly 12 seconds (60fps); higher values spin proportionally faster. |
| BANDS | 1–50 | Number of active displacement bands per frame. |
| SIZE | 1–120 | Base size of each band in pixels (along the band axis). |
| FOCUS | 0–1 | Biases where bands are distributed across the rotated span. 0.5 = even spread across the whole canvas. Toward 0 or 1 pulls bands toward one end of the span. Fixes the tendency of unbiased noise to cluster bands near the centre. |
| SHIFT | 0–0.5 | Maximum displacement perpendicular to the band axis, as a fraction of the canvas dimension along that axis. |
| SKEW | -1–1 | Position-based offset along the displacement axis, making bands angle diagonally relative to their own axis. |
| DRIFT | 0–3 | Dual-frequency noise driving band position along the rotated span: a slow base wander layered with faster, smaller jitter. Higher values increase both. |
| ROLL | -2–2 | Continuous scroll of all bands along the rotated span, independent of DRIFT. Positive and negative values scroll in opposite directions; 0 = no roll. |
| SPEED | 0–5 | Speed of the DRIFT/ROLL phase accumulation. Operates independently of glitch speed — works even with glitch off. |
| GAP | 0–200 | Snaps band positions to a regular grid spacing along the rotated span. |
| OPACITY | 0–1 | Alpha of displaced band content. Also scaled by the A/B Mix layer-priority weight. |
Global Mix Group
Reintroduces the clean source into the active effects chain at a selected serial position. Position determines whether the clean relationship enters recursive Feedback or only affects a later/final image. Pass 48 keeps this deliberately light and adds only a fader-response curve; no new render pass or image source is introduced.
| Control | Range / Options | Description |
| ON | toggle | Enable/disable. Zero MIX remains a true bypass. |
| BLEND | SCREEN / ADD / LIGHTEN / DODGE / MULTIPLY / DARKEN / BURN / OVERLAY / SOFT LIGHT / HARD LIGHT / DIFFERENCE / EXCLUSION / HUE / SATURATION / COLOR / LUMINOSITY / NORMAL | Canvas blend relationship between clean source and the current Process image. |
| MIX | 0–1 | Global Mix fader. |
| CURVE | LINEAR / SMOOTH / PUNCH | LINEAR is exact legacy behavior. SMOOTH eases both ends. PUNCH brings the clean relationship in earlier. The curve changes only the effective alpha and adds no image-processing pass. |
| POSITION | BEFORE FB / AFTER FB / AFTER FLOW / FINAL | Selects the legal insertion point in the fixed Classic serial pipeline. |
Solarize Group
THRESHOLD preserves the accepted HUFF Classic Solarize. LUMA QUANTIZE adds a Magic DaVE-inspired luminance quantiser using the same bounded Solarize scratch/readback path.
Pass 44 UI: inactive mode-specific controls are hidden. THRESHOLD shows THRESH + SOL R/G/B; LUMA QUANTIZE shows LEVEL + SOFT + INVERT. ON, MODE, AMOUNT and FLUIDITY remain visible in both modes.
| Control | Range | Description |
| ON | toggle | Enable/disable. |
| MODE | THRESHOLD / LUMA QUANTIZE | Select the original or new Solarize algorithm. |
| THRESH | 0–1 | THRESHOLD only. Original luminance threshold. |
| LEVEL | 0–100% | LUMA QUANTIZE only. Higher = coarser luminance contouring; 99% = two levels, 100% = luminance removed. |
| SOFT | 0–100% | LUMA QUANTIZE only. Softens the step transitions. |
| INVERT | toggle | LUMA QUANTIZE only. Reverses luminance while retaining chroma. |
| FLUIDITY | 0–100% | Solarize-local temporal slew. 100% = instantaneous Pass 42 behavior; lower values make Solarize evolve more slowly without changing playback speed or adding a new frame-skip gate. |
| AMOUNT | 0–1 | Shared wet/dry strength. |
| SOL R / G / B | 0–2 | THRESHOLD only. Existing per-channel tint multipliers. |
Flow Group
Noise-field UV displacement applied after Feedback. Each grid cell samples a Perlin noise field to determine where it pulls its source pixels from.
| Control | Range | Description |
| ON | toggle | Enable/disable. |
| STRENGTH | 0–20 | Maximum pixel displacement. |
| SCALE | 40–200 | Spatial scale of the noise field — grid cell size in pixels. |
| SPEED | 0–4 | Multiplies the time accumulator driving the noise field. 0 = frozen — the warp pattern stops evolving but stays applied. 1 = normal speed. |
| PULSE | 0–200 | Frames back in the ring to sample during warp. Adds temporal smear. 0 = sample the current buffer. |
| PULL | -1–1 | Radial bias added to the noise displacement. Positive values pull toward the canvas centre (implode). Negative values push away from centre (explode/centrifugal). 0 = pure noise field, no radial bias. |
| SWIRL | -2–2 | Rotates each cell's displacement vector by an angle proportional to its distance from centre, adding a vortex/spiral motion on top of the noise field and any PULL. Positive and negative values spin in opposite directions. |
| TURB | 0–1 | Blends in a second noise octave at higher frequency and lower amplitude, layered on top of the base field for more turbulent, less uniform displacement. 0 = single-octave field only. |
Presets
Presets are named snapshots of all current parameter values, stored in the browser's localStorage and listed in a dropdown for quick recall. JSON export/import provides portability across machines and sharing with collaborators.
| Control | Description |
| preset name field | Type a name, then click 💾 Save (or press Enter) to save the current parameter snapshot under that name. |
| 💾 Save | Saves the current snapshot to localStorage under the name in the field. Overwrites an existing preset of the same name. |
| — saved presets — dropdown | Lists all saved preset names alphabetically. Double-click an entry to load it. |
| ▶ Load | Loads the selected preset. Counts as one undo step. |
| ✕ Delete | Permanently removes the selected preset from localStorage. |
| ↑ Export JSON | Downloads all saved presets as a single timestamped .json file — a map of preset name → parameter snapshot. |
| ↓ Import JSON | Loads a previously exported file. A file containing a map of named presets merges all of them into your saved list (overwriting any name collisions). A file containing a single preset snapshot is imported under the name currently in the preset name field, or imported-<timestamp> if the field is empty. |
| Ctrl+Z / Cmd+Z | 10-step undo. Steps back through parameter changes one snapshot at a time. Loading a preset counts as one undo step. |
Presets are stored in the browser's localStorage — treat this as a cache, not a primary store. Use ↑ Export JSON to back up presets to a file you keep with your project. Cluster centre positions and velocities are runtime state and are not saved in presets; loading a preset restores all slider values but cluster centres will be wherever their physics simulation currently has them.
Keyboard Shortcuts
| Key | Action |
| P | Toggle the control panel. A pill indicator appears at the bottom of the screen reading "UI hidden · P to show" so you can always get back. |
| F | Toggle fullscreen. |
| Ctrl+Z / Cmd+Z | Undo the last parameter change. Up to 10 steps. |