Nodes/kubakub nodes/kubakub mask animate
ComfyUI Node

kubakub mask animate

Masks that move, on a curve, on the beat

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub mask animate
  • mask
  • field
  • audio
  • sound
  • masks
  • fps
  • audio
  • frame_count
  • report
◄effectreveal►
◄curveramp►
◄cycle2.00►
◄value_from0.00►
◄value_to1.00►
◄easinglinear►
◄soft0.05►
◄width0.20►
◄rings3►
◄trail0.00►
◄fps25.00►
◄seconds0.0►
◄scale1.00►
◄phase0.00►
◄duty0.50►
◄seed1►
◄listeneverything►
◄gain1.00►
◄release0.15►
◄nth1►
◄steps1►
◄threshold0.30►
◄gap0.10►
◄bpm0.0►
◄start0.0►
◄pivotmask centre►
◄wrapfalse►

What it's for

This is the node that makes a static building move. It outputs one mask per frame - a whole clip's worth - so a wipe travels across the facade, a band runs along a wall, an iris opens on a window, or the mask itself drifts, turns, scales or strobes.

Its natural partner is kubakub mask field, which supplies the grey ramp the move travels along. Mask field decides where; mask animate decides when and how. Chain two of them (masks output into the next node's mask input) and you get two moves at once - a wipe and a scale, a band and a strobe.

And it doesn't need a diffusion model to be useful: feed the masks into MaskToImage → Create Video and you've generated a projection-mapped animation with no AI in the loop at all. For a working VJ that's arguably the most valuable thing in the pack.

How it works

Two dropdowns do everything, and separating them is the whole design.

effect is what moves. Along the field: reveal (black to white), hide, band (a stripe travelling through), rings (stripes that keep coming). The mask itself: move x, move y (in picture widths/heights), rotate (in turns), scale (1 = as-is), opacity (0 to 1).

curve is how the value runs over time. ramp runs once and stays. saw runs again and again. triangle goes there and back. sine is the soft version of that. square is on/off - with opacity that's a strobe, with duty controlling how long the on part lasts. random picks a new value every cycle, noise wanders. Then the sound curves: sound level follows loudness, and beats / bars / low / mid / high hits each start a fresh ramp when one lands.

That last group is the party trick. Sound curves work with no audio connected - they fall back to a built-in 120 bpm beat - and with audio you get tempo detection, nth to use only every second or fourth hit, threshold and gap for detecting actual hits rather than rumble, and listen to pick which frequency band counts (kick, hats). steps is the one worth playing with: at 1, every beat replays the same move; at more than 1, each beat advances by that many steps, which is how you get one more region lighting up per beat when the field is a region order ramp.

The curve is literally drawn on the node - buttons set the type, dragging left/right on the curve changes the speed. Small thing, but it means you can dial a tempo without staring at numbers.

Inputs and outputs

Set these first: effect, curve, cycle (seconds per cycle - or for beats and hits, seconds the ramp takes after each one), value_from / value_to (the bottom and top of the curve, in whatever units the effect uses), easing, and width/rings/soft for the band and ring effects.

Then the ones you'll come back to: trail (seconds a place keeps glowing after the mask has moved past - 0 by default, and it's the difference between a wipe and a comet), fps, seconds (0 means take the length from the sound, else the mask batch, else 4 seconds), and scale (0.05 to 1, mask resolution relative to the input - at 250 masks of 3840×2160 a full-size batch is around 8 GB of RAM, so scale down while you're iterating).

Optional inputs: mask (what's being animated - for the field effects it limits the result), field (the ramp; empty means a plain left-to-right ramp over the mask), audio, plus phase, duty, seed, listen, gain, release, nth, steps, threshold, gap, bpm, start, pivot and wrap for the specific curve and effect you picked.

Outputs: masks (one per frame), fps, audio (the sound, cut to the frames - silence if none, so it's always safe to wire into Create Video), frame_count, and report (frames, size, the curve's range, and whatever tempo or hits it found). That fps/audio pair is what makes the output directly video-ready.

Install

Manager → search kubakub nodes → install → restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt

ComfyUI 0.37.0+; opencv-python-headless is the only added package (keep an existing OpenCV build). Both mask nodes landed in 0.3.0 and added no new dependencies. There's a model-free example workflow - example_workflows/mask_animate.json - that runs with nothing connected.

Common issues

  • RAM explosion. 250 frames of 4K float masks is about 8 GB. Drop scale to 0.5 while you tune, and set seconds to something honest.
  • The sound curves do nothing useful. Check bpm (0 = detect, and detection is only as good as the track), threshold for hits, and listen so your kick isn't being masked by hi-hats.
  • Nothing connected, still got masks. By design - it runs a sample. Great for learning, confusing the first time.
  • Two moves at once. Chain two nodes: the first node's masks into the second's mask. It's the documented approach, not a hack.
Categorykubakub/2d/masks

Inputs (31)

NameTypeDefaultDescription
effectCOMBOrevealAlong the field: reveal (appears from black to white), hide, band (a stripe travels through), rings (stripes that keep running). The mask itself: move x / move y (value = picture widths / heights), rotate (value = turns), scale (value = size, 1 = as it is), opacity (value 0 to 1; with a square curve = strobe).
curveCOMBOrampHow the value runs. ramp: once, then it stays. saw: again and again. triangle: there and back. sine: a soft there and back. square: on / off. random: a new value every cycle. noise: wanders. sound level: follows the loudness. beats / bars / low / mid / high hits: each one starts a ramp.
cycleFLOAT2.000.01–3600Speed: seconds for one cycle of the curve (for beats and hits: seconds the ramp takes after each one).
value_fromFLOAT0.00-100–100The value at the bottom of the curve. reveal / band / rings / opacity: 0 to 1. move: picture widths or heights (-0.5 = half a picture to the left / up). rotate: turns. scale: size.
value_toFLOAT1.00-100–100The value at the top of the curve.
easingCOMBOlinearramp, saw, triangle, beats and hits: how the ramp starts and stops.
softFLOAT0.050–1reveal / hide / band / rings: how soft the moving edge is (0 = hard, 1 = the whole field fades at once).
widthFLOAT0.200.01–1band / rings: how wide a stripe is (1 = the whole field).
ringsINT31–64rings: how many stripes.
trailFLOAT0.000–60Seconds a place keeps glowing after the mask has moved on. 0 = no trail.
fpsFLOAT25.001–120Frames per second.
secondsFLOAT0.00–3600Length. 0 = the length of the sound, else of the mask batch, else 4 s.
scaleFLOAT1.000.05–1Size of the masks relative to the input (RAM: 250 masks at 3840x2160 = 8 GB).
maskoptMASKWhat is animated: a mask, or a mask batch (one per frame, e.g. from another kubakub mask animate). For reveal / hide / band / rings it limits the result.
fieldoptMASKFor reveal / hide / band / rings: the grey ramp from kubakub mask field. Empty = a left to right ramp over the mask.
audiooptAUDIOFor the sound curves, and passed on to 'audio' for Create Video. A sound curve without a sound runs on a built-in beat (120 bpm).
phaseoptFLOAT0.000–1Where in its cycle the curve starts (0.5 = half a cycle later).
dutyoptFLOAT0.500.01–0.99square: the part of the cycle it is on (0.1 = short flashes).
seedoptINT10–2147483647random / noise: another run.
listenoptCOMBOeverythingsound level: the whole sound, or only its low (kick, bass), mid or high (hats, clicks) frequencies.
gainoptFLOAT1.000–10sound level: how strongly the loudness drives the value.
releaseoptFLOAT0.150–5sound level: seconds the value takes to fall after a peak.
nthoptINT11–64beats / bars / hits: only every nth one counts.
stepsoptINT11–512beats / bars / hits: 1 = each one runs the whole move again. More = each one moves on by one step of that many (e.g. the number of regions with a 'region order' field: one more region per beat).
thresholdoptFLOAT0.300–1low / mid / high hits: how strong a hit has to be to count.
gapoptFLOAT0.100–10low / mid / high hits: the shortest time between two.
bpmoptFLOAT0.00–400beats / bars: a tempo you know. 0 = found in the sound.
startoptFLOAT0.00–3600Seconds into the sound where the frames start.
pivotoptCOMBOmask centrerotate / scale: around the mask's own centre or the middle of the picture.
wrapoptBOOLEANfalsemove: what leaves on one side comes back in on the other.
soundoptKUBA_SOUNDFrom kubakub sound: the sound and how it is heard (tempo, gain, release, band, threshold, gap), set once for every node that listens, so all of them step on the same beat. Connected, it comes before 'audio' and before this node's own sound settings.

Outputs (5)

NameTypeDescription
masksMASKOne mask per frame.
fpsFLOATFrames per second.
audioAUDIOThe sound, cut to the frames (silence without one).
frame_countINTHow many frames.
reportSTRINGFrames, size, the range of the curve, tempo or hits found.