MVEx Subject Crop
Stop Your Video Crops From Jittering (and Reading as Camera Motion)
- original_images
- masks
- cropped_images
- cropped_masks
- bboxes
- debug
The problem this node solves is the reason most video inpainting looks wrong, and it's not the inpainting. If you crop around a moving subject frame-by-frame - the obvious way to give a video model a tight, high-res region to work on - the crop box shimmies. Position and size wobble with every mask hiccup, and video models read that wobble as camera motion. The subject drifts, the background crawls, and you get a mess no denoise setting can fix.
MVEx Subject Crop from MaskVidExperiments avoids the whole class of problem by refusing to decide each frame on its own. It looks at the entire clip's masks, then plans position, size, and shape together so the crop holds still through mask noise, occlusions, and brief excursions - and follows only sustained motion. The output batch is stable by construction, not by luck.
How it works
You feed it the frame batch plus a subject mask per frame, and pick a mode:
- combined - one static crop with padding around the subject's whole travel. Simplest; right for a subject that mostly stays put.
- tracked - a constant-size crop that stays still until the subject would leave it, then moves as little as possible. Pixel-exact slices, no resampling, so the crop keeps full detail.
- zoomed - the crop also follows the subject's size and is resampled to a fixed output resolution, so the subject holds a constant share of the frame. Use this when the subject grows or shrinks a lot over the clip.
The author's own stress tests (moving approach, occlusion dips, side-to-side oscillation, hard cuts, off-screen entry) are in the repo README as GIFs, and the pitch holds up: the crop doesn't chase reversals, doesn't hunt before a scene cut, and doesn't lurch when half the mask vanishes for a stretch.
The inputs that matter
For a first run you mostly touch two things inside the mode dropdown: crop_scale (crop size as a multiple of the subject's extent - 1.5 means a third of the crop is margin) and, in tracked/zoomed, padding and prefer. padding says how firmly that margin is kept (guaranteed / firm / flexible), prefer says what pays for it when the subject moves (stillness keeps the crop big and calm, tightness keeps it small and moves it more). The defaults - firm, stillness - are sane for most clips.
Outside the dropdown: divisible_by (default 16) rounds the crop up to the model's resolution requirement, and upscale_megapixels upscales every crop to roughly that many megapixels so you don't need a resize node on either side. Set crop_scale to 0 and cropping is skipped entirely - the whole frame passes through, still resized to the grid, which makes A/B-testing with the pipeline off trivial.
The outputs
- cropped_images - the constant-size crops, one per frame. Into your sampler.
- cropped_masks - the masks cut to the same boxes; feed these to Subject Uncrop to confine the paste to the subject.
- bboxes - the per-frame boxes, which is what Subject Uncrop needs to paste back.
- debug - a string summarizing the plan (shape, box sizes, movement, how much padding promise was kept). Route it to a Preview Any node when the crop looks wrong; it tells you whether the planner's math or your masks are the problem.
Install and gotchas
It ships in the MaskVidExperiments pack, from drozbay - the same person who maintains RES4LYF and built the Wan VACE tooling, so the video pedigree is real. Install via ComfyUI Manager (search "MaskVidExperiments") or:
cd ComfyUI/custom_nodes
git clone https://github.com/drozbay/MaskVidExperiments
then restart ComfyUI. No model files, no extra dependencies beyond ComfyUI's own - just needs ComfyUI v0.15.0+ because it's written against the newer node API.
Two things bite people. First, garbage-in: a noisy segmentation mask is the top cause of a jumpy crop, because mask noise counts as subject. Run the masks through MVEx Mask Cleanup first - the pack's own pipeline does. Second, "guaranteed" padding is a real promise, and the only thing allowed to break it is the image edge, so don't pick it until your masks are clean. This is a video-tools pack, not a single-image one - for one-off stills the mature choice is still ComfyUI-Inpaint-CropAndStitch; this pack exists for the clip where that workflow jitters.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| original_images | IMAGE | Video frames as a batch. | |
| masks | MASK | Subject masks, one per frame. Clean them first (Mask Cleanup) if the segmentation is noisy. | |
| mode | COMBO | In order of increasing complexity. combined: one static crop with padding around the subject's whole travel. tracked: a constant-size crop that stays still until the subject would leave it, then moves as little as possible. zoomed: the crop also follows the subject's size, planned over the whole clip, every crop resampled to a fixed output resolution. | |
| divisible_by | INT | 16 | Crop width and height are rounded up to a multiple of this. Match the model's resolution requirement. |
| upscale_megapixels | FLOAT | 0.00-16–16 | Upscale the cropped images/masks to this many megapixels, on the divisible_by grid, using bicubic for images and nearest exact for masks. Set to 0.0 to disable. (Use a negative value to allow scaling down as well as up.) |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| cropped_images | IMAGE | Constant-size crops, one per frame. |
| cropped_masks | MASK | The input masks cropped to the same boxes. Feed to Subject Uncrop to confine the paste to the subject. |
| bboxes | BOUNDING_BOX | One box per frame, for Subject Uncrop. |
| debug | STRING | Summary of the plan: chosen shape, box sizes, movement, and how much of the padding promise was kept. |