MultiCutAndDragOnPath
Cut them out and drag them along a path
- image
- masks
- bg_image
- image
- mask
Most "make the thing move" nodes ask a diffusion model to imagine the motion. This one doesn't. MultiCutAndDragOnPath - the flagship of Pablerdo's small, personal ComfyUI-MultiCutAndDrag pack - physically cuts objects out of your image with masks and re-composites them at new positions, one frame at a time. The output is a batch of frames showing a deterministic, hand-authored animation. No inference, no hallucinated in-between motion, just pixel-precise "this object travels from here to here" that you're in full control of.
That's a genuinely different tool from AnimateDiff or Wan, which invent the motion. If you want a specific movement - a subject sliding across a scene - this gives you exact control instead of hoping the model cooperates. It's tagged experimental in its own pack, so set expectations: a tinkerer's tool, not a polished product. But it fills a real gap.
How it works
Each mask you feed in defines one region to cut. The node finds the mask's bounding box, crops that region out of your input image, and stores it. Your coordinate_paths then tells it where each cut region goes per frame.
Coordinate paths are a JSON array of arrays of {"x": ..., "y": ...} objects - one path per mask, and every point in a path is one output frame:
[
[{"x": 400, "y": 240}, {"x": 720, "y": 480}, {"x": 900, "y": 300}],
[{"x": 50, "y": 150}, {"x": 40, "y": 200}, {"x": 30, "y": 250}]
]
Three paths, three masks, three points each → three output frames. For each frame it starts from the background and pastes each cut region centered on that frame's coordinate - the region's center lands on the coordinate, which matters for background placement.
The background comes from one of two places. With inpaint on (the default), the node runs cv2.inpaint (Telea) once over the union of all the cut bounding boxes, filling the holes. Alternatively you can pass a bg_image and it uses that untouched - which is the route most people end up taking, because...
The inpainting is the trap. It fills the bounding box of each mask, with a 5px border, not the exact silhouette. So a non-rectangular object leaves a visible rectangular smear behind it as it moves. If you want a clean result, inpaint the background properly yourself (SAM mask + a real inpainting pass, or just a clean plate) and feed it in as bg_image with inpaint off.
rotation adds per-region spin: pass degrees as a JSON array (one total rotation per mask, in degrees) and each region rotates smoothly across the frames as it travels.
Inputs and outputs that matter
image- the frame(s) you're cutting from. Only the first is used.masks- one mask per region you want to move; count must match the number of coordinate paths.coordinate_paths- the JSON shown above. This is where the effort lives.frame_width/frame_height(default 512) - keep these equal to your input image size. The mask canvas is alwaysframe_size, while the image canvas is the size of the input orbg_image. Mismatch them and yourimageandmaskoutputs come back at different resolutions.inpaint(bool, default true) andbg_image(optional) - see above.rotation(bool, default false) anddegrees(optional JSON array) - spin.
Outputs: image (a batch of frames, ready for AnimateDiff, a video encoder, or VideoHelperSuite) and mask (per-frame masks of the moved regions, handy for compositing or inpainting downstream).
Installation
cd ComfyUI/custom_nodes
git clone https://github.com/Pablerdo/ComfyUI-MultiCutAndDrag
Restart ComfyUI, or grab it from ComfyUI Manager by searching "MultiCutAndDrag". The pack needs the usual suspects - torch, torchvision, numpy, Pillow, scipy, opencv-python - and its requirements.txt also lists mss, peft, color-matcher and friends that the node code never actually imports. You can install the lot; nothing heavy gets downloaded, and there are no model files in this pack.
Common issues
- Path count ≠ mask count raises a
ValueError- the node checks this and tells you. - Uneven path lengths don't raise; the frame count comes from the first path, so a shorter path dies with an
IndexErrormid-run. Make every path the same length. - Mismatched resolution between image and mask outputs when
frame_width/frame_heightdon't match the input - the most common silent surprise. - Rectangular inpaint artifacts behind moving objects - swap in your own
bg_image. - Coordinates are in pixels and subpixel values get truncated, so keep your keyframe positions on whole numbers.
It's rough around the edges, but for "I know exactly how I want this object to move," nothing else in ComfyUI does it more directly.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| coordinate_paths | STRING | — | |
| masks | MASK | — | |
| frame_width | INT | 51216–4096 | — |
| frame_height | INT | 51216–4096 | — |
| inpaint | BOOLEAN | true | — |
| rotation | BOOLEAN | false | — |
| bg_imageopt | IMAGE | — | |
| degreesopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |