Video MaskBasedSplit
Cut a video into segments wherever the mask goes empty
- images
- masks
- audio
- image_segments
- mask_segments
- audio_segments
If you've built a workflow that tracks or masks a subject across a clip, you've probably noticed the mask sometimes drops to nothing - the subject walks out of frame, a shot cuts, or you deliberately zeroed the mask as a marker. Video_MaskBasedSplit turns "the mask goes empty here" into "cut the video here," automatically, instead of you scrubbing the timeline by hand looking for the boundary.
It's part of the ComfyUI-WJNodes pack - a personal utility collection, so don't expect a tutorial or a wiki entry for this specific node beyond what its own name and inputs tell you.
How it works
On every frame, the node checks how much of the mask is actually "on." Once that coverage drops below empty_threshold, it starts counting consecutive near-empty frames; once that count reaches empty_frames_count, that position becomes a cut point. The clip is split there, and the process repeats for the rest of the sequence - so a long video with a mask that empties out several times can come back as several segments, not just two. Any resulting segment shorter than min_segment_frames gets discarded instead of being handed downstream as noise.
The two counting thresholds exist for the same reason: real masks are messy. empty_threshold stops a single noisy or slightly-dirty frame from reading as "empty" when it isn't really. empty_frames_count stops a single flickered frame from triggering a false cut on its own - you generally want several consecutive empty frames before you trust that the subject is genuinely gone, not just occluded for an instant.
The inputs and outputs that matter
images/masks(required) - your video and its frame-aligned mask sequence. These need to correspond frame-for-frame.empty_threshold(float, default 0.01) - how little mask coverage counts as "empty." Raise this if a slightly noisy mask is preventing clean splits from registering.empty_frames_count(int, default 1) - how many consecutive empty frames are needed before a cut is confirmed. Raise this if brief flickers in your mask are causing false splits.min_segment_frames(int, default 5) - segments shorter than this are dropped rather than output.audio(optional) - if you have an audio track, it gets split along with the video and mask.image_segments/mask_segments/audio_segments- these are list outputs, not a single combined batch. Each is a list of separate clips, so a downstream node built to handle lists (this same pack'sSaveMP4_batch, for instance) processes each segment individually rather than treating the output as one long batch.
How to install it
Via ComfyUI Manager: search "ComfyUI-WJNodes," install, restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/807502278/ComfyUI-WJNodes
then restart. No model downloads required - this is pure frame-by-frame tensor math, nothing to fetch from disk. You do need an actual masking step feeding this node, though; it has nothing to split on without one.
Common issues & troubleshooting
If you get one giant segment back instead of several, your mask probably never actually reaches your threshold - check the real pixel values coming out of your masking step against empty_threshold, since "empty" here means below a threshold, not literally all-zero unless you set the threshold to 0.
If you get a flood of tiny, useless segments, raise min_segment_frames and/or empty_frames_count so brief flickers in the mask stop registering as real cuts. And if images and masks don't line up frame-for-frame to begin with - different lengths, different frame rates upstream - fix that first; a split node can't reason about a mismatch it isn't told about.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| masks | MASK | — | |
| empty_threshold | FLOAT | 0.010–1 | — |
| empty_frames_count | INT | 11–100 | — |
| min_segment_frames | INT | 51–1000 | — |
| audioopt | AUDIO | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_segments | IMAGE | — |
| mask_segments | MASK | — |
| audio_segments | AUDIO | — |