Animated Shape Mask
Procedural mask reveals, no drawing required
- IMAGE
- num_shades
- width
- height
Animating a mask is one of those things that sounds easy until you try it - you need a moving region that changes every frame, and drawing 64 of them by hand is miserable. Animated Shape Mask is the cheat code: it generates a whole mask animation procedurally from a handful of parameters. Moving bands, traveling sine waves, expanding or contracting circles - pick a mode, pick a resolution, and out comes an image sequence where each frame is a mask you can drive an inpainting reveal with.
This is the sibling of Animation_RGB_Mask in the Eden pack, and the family resemblance shows: one generates color-coded region animations, this one generates grayscale shape masks. If your goal is a clean binary or shaded mask sweep - like a cinematic reveal where content is masked in as a band moves across - this is the node.
How it works
Under the hood it's a MaskAnimationGenerator that renders each frame's mask at your chosen width/height, then stacks the frames into an IMAGE batch. The modes break into three families:
- moving_band_ - a solid band sweeping across the frame (top-down, bottom-up, left-right, right-left).
- sine_wave_ - a wavy band, with
wave_frequencycontrolling ripple andwave_amplitude_ratiocontrolling wobble, sweeping across in one of four directions. - expanding_circle / contracting_circle - a circle growing from or shrinking to the center.
Two knobs matter more than the rest. num_shades (default 2) sets how many grayscale levels the mask uses - 2 gives hard black/white, which is what you want for feeding a real inpainting mask. Crank it to 16–64 and you get smooth gradient shades instead, which looks great composited but behaves differently when a KSampler treats it as a mask. invert_mask flips which side is active, useful when you want content to leave instead of arrive.
There's also a gradient_type (none / all_edges / trailing_edge) plus gradient_width_ratio that softens mask edges with a distance-based falloff (via OpenCV's distance transform) - all_edges fades every boundary, trailing_edge fades only the moving edge, which gives a lovely blur-sweep reveal effect.
The outputs
- IMAGE - the mask animation,
total_framesframes of width×height. - num_shades, width, height - echoed back as INTs so downstream nodes can use them without guessing.
Wire the IMAGE into a mask-conversion node and then into Set Latent Noise Mask on an inpaint KSampler, and you've got a frame-consistent animated reveal. The KB's inpainting essay is worth a re-read here: masked inpainting still owns bit-identical unmasked pixels, which is exactly the property an animated reveal needs - the already-revealed area stays frozen while only the newly exposed band regenerates.
Installing
It's part of edenartlab/eden_comfy_pipelines (Eden.art nodesuite):
cd ComfyUI/custom_nodes
git clone https://github.com/edenartlab/eden_comfy_pipelines.git
cd eden_comfy_pipelines
pip install -r requirements.txt
Or ComfyUI Manager → search "Eden". It needs opencv-python (in the pack's requirements) for the gradient falloff, but nothing else exotic.
Gotchas
Two real ones. First, the binary-mask trap: the pack prints a warning if you set gradient_type to anything but none while num_shades is 2 - gradients need multiple shades to exist, so you'll get a hard mask and wonder why your soft fade didn't happen. Second, remember the output is IMAGE, not MASK - most inpainting nodes want a MASK, so throw it through a converter (or use it as IMAGE conditioning) before it hits a KSampler. And don't forget the obvious: a total_frames of 64 at 512×512 is a chunk of VRAM when it's stacked as a single batch, so keep resolutions sane for long sweeps.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| width | INT | 51224–9223372036854776000 | Output width in pixels. |
| height | INT | 51224–9223372036854776000 | Output height in pixels. |
| total_frames | INT | 641–9223372036854776000 | Number of frames in the animation. |
| num_shades | INT | 22–256 | Gray levels. 2 = hard black/white mask; use 16+ to see gradients. |
| mode | COMBO | Shape and motion direction (td/bu = top-down/bottom-up, lr/rl = left-right/right-left). | |
| invert_mask | BOOLEAN | false | Swap shape and background shades. |
| band_thickness_ratio | FLOAT | 0.200.01–1 | Band thickness as a fraction of the frame (moving_band modes). |
| wave_amplitude_ratio | FLOAT | 0.100–0.5 | Wave amplitude as a fraction of the frame (sine_wave modes). |
| wave_frequency | FLOAT | 2.00.1–20 | Number of wave periods across the frame (sine_wave modes). |
| wave_thickness_ratio | FLOAT | 0.050.01–0.5 | Wave line thickness as a fraction of the frame (sine_wave modes). |
| gradient_type | COMBO | none | Soft edge style: around all edges, or only behind the direction of motion. |
| gradient_width_ratio | FLOAT | 0.000–1 | Gradient width relative to the shape size. 0 = hard edges. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | Mask animation frames (grayscale IMAGE). |
| num_shades | INT | Number of gray levels used. |
| width | INT | Width in pixels. |
| height | INT | Height in pixels. |