Remove an object from a video: ProPainter
Lesson "video-remove", in the group Packs and tools of the lesson list. Steps: 8.
What you will be able to do
An object marked by a mask video disappears, and the background behind it is filled in from the neighbouring frames.
What you need
- It goes on from Load, cut and save video: VideoHelperSuite. The card says so; it is a hint, not a lock.
- Node packs: ComfyUI-VideoHelperSuite, ComfyUI_ProPainter_Nodes. You install them in ComfyUI yourself, then choose Sync ▸ Sync now. Until then the card says the lesson does not fit and names the pack.
- Nodes: Load Video (Upload) 🎥🅥🅗🅢 / VHS_LoadVideoPath, Convert Image to Mask, ProPainter Inpainting, Video Combine 🎥🅥🅗🅢.
- The app downloads and installs nothing. The step texts below say which files and folders, and which ComfyUI template names them.
The steps
The words of each step, as the lesson shows them. Node names are in bold.
What it costs, first (reading)
This lesson needs the ComfyUI_ProPainter_Nodes pack. Install it yourself through ComfyUI's manager. A pack runs other people's code on your computer, so take it from its official page and keep it up to date. The example also uses ComfyUI-VideoHelperSuite to load and save.
ProPainter follows the motion between frames and fills a masked area with what the other frames show behind it. It needs two videos of the same length: the clip, and a mask video where the object to remove is red (or white) and the rest black. A mask video is made in a video editor or with a segmentation pack such as SAM2.
What it costs: its models are small; the pack fetches them itself into its own folder when the graph is first run in ComfyUI. Memory grows quickly with the size and the number of frames; the example halves the size and takes 24 frames.
If the canvas already holds another graph, start from an empty one: "File ▸ New project".
Load the clip
Add a Load Video (Upload) 🎥🅥🅗🅢 node, choose the clip in
videoand setframe_load_capto 24.Try a short piece first: the work grows with every frame.
Load the mask video
Add a second Load Video (Upload) 🎥🅥🅗🅢 node, choose the mask video in
videoand set the sameframe_load_capandskip_first_framesas for the clip.The mask must match the clip frame for frame; a shift of one frame leaves a ghost of the object.
Turn the mask video into a mask
Add a Convert Image to Mask node, connect the frames of the mask video to its
imageinput and setchanneltored.The node reads one colour of each frame as the mask: where it is bright, the object is removed.
Remove the object
Add a ProPainter Inpainting node. Connect the frames of the clip to
imageand the output of Convert Image to Mask tomask. Setwidthto 640 andheightto 480 (the size of your frames) andmask_dilatesto 5.mask_dilateswidens the mask by a few pixels, so the edge of the object does not stay behind.If the frames are large, put an Upscale Image By node with 0.5 before both inputs, as the example does; the app accepts it on the way.
Save the result
Add a Video Combine 🎥🅥🅗🅢 node, connect the
IMAGEoutput of ProPainter Inpainting toimagesand setframe_rateto 24, the rate of the clip.When the result is not right (reading)
- A shadow or an edge of the object remains: raise
mask_dilatesto 8-10, or widen the mask itself. - The filled area is blurry: the background behind the object is never seen in the clip; ProPainter can only invent it roughly.
- Out of memory: fewer frames, or a smaller size.
- A shadow or an edge of the object remains: raise
The graph is ready (reading)
Save the graph with "File ▸ Save workflow for ComfyUI…", open the file in ComfyUI and run it there. This app runs nothing in ComfyUI itself.
What the lesson checks
A reading step is done when you press Got it, next. A doing step ticks itself off when the canvas holds:
- Step 2, Load the clip:
- a Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath node.
videoof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (clip): a value is chosen.frame_load_capof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (clip) is from 1 to 300; Do this for me sets 24.
- Step 3, Load the mask video:
- a Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath node.
videoof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (mask video) is not the same file asvideoof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (clip).frame_load_capof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (mask video) equalsframe_load_capof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (clip).
- Step 4, Turn the mask video into a mask:
- a Convert Image to Mask node.
IMAGEof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (mask video) intoimageof Convert Image to Mask (a Upscale Image or Upscale Image By or ImageFromBatch or ImageResizeKJv2 or Resize Image or GetImageRangeFromBatch or ResizeImageMaskNode in between is accepted).channelof Convert Image to Mask isred.
- Step 5, Remove the object:
- a ProPainter Inpainting node.
IMAGEof Load Video (Upload) 🎥🅥🅗🅢 or VHS_LoadVideoPath (clip) intoimageof ProPainter Inpainting (a Upscale Image or Upscale Image By or ImageFromBatch or ImageResizeKJv2 or Resize Image or GetImageRangeFromBatch or ResizeImageMaskNode in between is accepted).MASKof Convert Image to Mask intomaskof ProPainter Inpainting.widthof ProPainter Inpainting is from 64 to 2560; Do this for me sets 640.heightof ProPainter Inpainting is from 64 to 2560; Do this for me sets 480.mask_dilatesof ProPainter Inpainting is from 0 to 20; Do this for me sets 5.
- Step 6, Save the result:
- a Video Combine 🎥🅥🅗🅢 node.
IMAGEof ProPainter Inpainting intoimagesof Video Combine 🎥🅥🅗🅢.frame_rateof Video Combine 🎥🅥🅗🅢 is from 1 to 60; Do this for me sets 24.