Video Motion Mask
Isolate what moves, ignore the camera
- video
- motion
- mask
- video
Every "only affect the moving thing" workflow runs into the same wall: the camera moves too, so a naive frame-difference mask lights up the entire frame the moment you pan. Video Motion Mask is the node that knows the difference. It measures motion between frames, subtracts the background's own motion - the pan, and the parallax the pan causes - and leaves you a per-frame mask of what actually moved in the world.
That mask is the thing you feed to SAM, to an inpainting pass, or to any effect that should touch only the subject. And because the companion nodes in this family take masks too, it pairs neatly: make the mask here, then keep a subject sharp in Video Motion Blur or let it lead the window in Video Reframe.
Inputs and outputs
video is the clip, at least two frames. threshold is speed in pixels per frame that counts as moving: 0.5 catches slight motion, 1.0 is the default, 4.0 is only fast action. Turning it down is how you catch a breathing subject; turning it up is how you stop a wobbling tree from being masked as a subject.
ignore_camera is the switch that earns the node its place. true subtracts the background's motion including parallax, so a moving shot masks only its subjects. Set it false and everything the camera sweeps past counts - which is occasionally what you want, for a "what did the camera reveal" mask.
grow widens the mask by N pixels (0 = as measured, 4 default, 16 generous) and feather softens the edge (0 hard, 2 default, 8 soft). If you are feeding inpainting, err generous on both: a mask that is one pixel too tight is what produces a halo of the old subject around the new one.
motion is optional and takes a shared measurement from Video Motion, which saves a full flow pass if other nodes in the graph need the same thing. Empty, it measures here at 768 px.
Two outputs. mask is white where something moves, one mask per frame at the clip's size - this is the one you wire onward. video is the clip with what moves tinted red, which is the sanity check: if the red is on the subject, the settings are right, and if it is on the background, they are not.
The workflow it slots into
This is a detection node, not a segmentation node. It finds motion; it does not know what the moving thing is. Feed its mask to something that does - SAM 3 for a text-prompted subject inside the motion region, or a tracker that carries an identity from frame to frame - and you get a clean subject mask for the whole clip, cheaply, without segmenting every frame from scratch.
That combination is the practical reason to have this in the pack at all. Per-frame segmentation on a 200-frame clip is expensive and flickers; motion gives you the region and the segmenter only has to do the hard part inside it.
Install
ComfyUI Manager → search WAS Node Suite v3 → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
ComfyUI 0.14.0+ and Python 3.10+. The pack installs no packages of its own - requirements.txt is a comment and pip never runs - so nothing here drags in scipy, OpenCV or scikit-image the way the v2-era suite did. This node needs no model files. If you also want the learned flow option, the weights live in ComfyUI/models/optical_flow and are only fetched when you turn features.network on in config.yaml.
Where it goes wrong
A mostly-still subject. threshold 1.0 is a real pixel-per-frame speed, and someone standing and talking moves less than that. Drop to 0.5 and expect noise; grow and feather exist partly to clean that up.
A pan with heavy parallax. Foreground moves much faster than background at the same camera speed. ignore_camera: true handles the steady case well, but a shot with a close-up railing sliding past in the foreground will still leak that railing into the mask. That is physics, not a bug - mask the railing out, or raise threshold and accept missing slower subject motion.
Empty masks after a cut. Cut handling comes from the flow measurement, and a cut is a frame pair with no meaningful motion. Expect a one-frame blip at each cut; if it matters, split the clip at its scenes first with Video Split Scenes and mask each scene separately.
Masks that flicker on the edges. Feathering a motion-compared mask widens and narrows the boundary frame to frame. Set feather to 0 while you tune threshold, then add softness back once the region is stable.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | The clip, at least two frames. | |
| threshold | FLOAT | 1.00–100 | Speed, in pixels per frame, that counts as moving: 0.5 = catches slight motion; 1.0 = default; 4.0 = only fast action. |
| ignore_camera | BOOLEAN | true | `true` = the background's motion, a pan and its parallax included, is taken away, so a moving shot masks only its subjects; `false` = everything the camera sweeps past counts. |
| grow | INT | 40–256 | Pixels the mask is widened by: 0 = as measured; 4 = default; 16 = generous. |
| feather | FLOAT | 2.00–64 | Softness of the mask's edge in pixels: 0 = hard; 2 = default; 8 = soft. |
| motionopt | WAS_MOTION | Motion from Video Motion, measured from this same clip at any size. Left empty, it is measured here at 768 px on the long side. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mask | MASK | White where something moves, one mask per frame at the clip's size. |
| video | VIDEO | The clip with what moves tinted red, for saving or showing elsewhere: same size, length, frame rate and audio. |