ProPainter — Temporal / Remove / Stitch / Refine / Flow
Five ProPainter operations in one node, from temporal inpaint to flow refine
- images
- masks
- stitch_data
- inpainted_image
- stitched_image
- mask_override
- frame_a
- frame_b
- flow_mask
- image_out
- mask_out
- aux_image
- aux_mask
- info
Masked inpainting has a video-sized problem: a per-frame inpaint model will happily give you a clean frame, and then the person's arm flickers between frames because the model re-generated it differently every time. ProPainter is the standard answer - it inpaints across time, using optical flow to propagate the fill so the result holds together as video. This node bundles the whole ProPainter workflow into one dispatcher with five modes, which is both its strength and the thing you have to read carefully.
The five modes
ProPainterMEC is a mode dropdown in front of one big shared input panel. Pick a mode and only the relevant widgets are read; everything else is ignored. That keeps one node instead of five, at the cost of a busy panel you learn to skim:
- remove (default) - the classic object/wire/timestamp removal. Feed
images+masks, it uses RAFT flow and ProPainter's InpaintGenerator to fill the masked region over the whole clip.remove_qualitypresets (fast/balanced/quality) override the manualraft_iter/neighbor_stride/ref_stride/subvideo_lengthknobs - start with balanced.remove_dilate_pixels(3) dilates the mask to cover anti-aliasing fringes. - temporal - same fill machinery but with
stitch_datafrom InpaintCropProMEC, so it blends the inpaint with the original at the crop boundary. This is the one for crop → temporal inpaint → stitch-back pipelines. - stitch - takes a crop-sized
inpainted_imagefrom any generative inpaint and blends it back into the canvas via the crop's stitch data, withboundary_band_pixels(12) re-painting just the seam andpreserve_inpaint_centerkeeping your generative fill untouched in the middle. - stitch_refine - cleans up an already-stitched
stitched_image: re-runs flow refine around the seam ring (ring_pixels, default 8) to kill the telltale stitched-frame shimmer. - flow - pure optical-flow tooling:
frame_a/frame_bin, gives you the flow field visualization plus aconsistencymask, no inpainting. Pairs with OpticalFlowMEC.
Shared knobs that matter
Shared knobs that matter: subvideo_length (default 8) is the frames-per-InpaintGenerator window, and the tooltip gives the VRAM cheat sheet - 8GB cards want 8–30, 12GB can do 40–60, 24GB runs 80+. color_match_mode (default reinhard) does per-frame masked color matching between fill and surroundings. Outputs are image_out, mask_out (fill/repaint/consistency per mode), aux_image (flow RGB in flow mode), aux_mask, and an info string with timings and coverage.
Install is the one real hurdle
The install is the one real hurdle. The pack's requirements call for the ProPainter bridge installed manually - pip install git+https://github.com/sczhou/ProPainter.git - because it's not on PyPI. RAFT + RFC + Inpaint weights auto-download from the project's GitHub release on first use. So: clone Code2Collapse/ComfyUI-CustomNodePacks into custom_nodes (or Manager → "CustomNodePacks"), run the ProPainter pip install, restart, and the node appears under C2C/Inpaint. It needs real VRAM and a GPU that doesn't choke on RAFT.
Where people get burned
Where people get burned: expecting frame-perfect results on fast, occluding motion (flow lies at occlusion - that's what mask_out in flow mode is for), and cranking subvideo_length on an 8GB card until it OOMs. The pack's own inpainting docs also remind you that flow-based fill is best at removing things cleanly, not at replacing them with complex detail - if the removed area needs brand-new content, layer a generative inpaint on top via the stitch path instead of expecting ProPainter to invent it.
Inputs (25)
| Name | Type | Default | Description |
|---|---|---|---|
| mode | COMBO | remove | Pick the ProPainter operation. Each mode reads a different subset of the optional inputs/widgets below. |
| use_half | BOOLEAN | true | — |
| color_match_mode | COMBO | reinhard | Per-frame masked colour match between fill and surroundings (ignored in 'flow' mode). |
| raft_iter | INT | 121–100 | — |
| neighbor_stride | INT | 51–32 | — |
| ref_stride | INT | 101–64 | — |
| subvideo_length | INT | 82–300 | Frames per InpaintGenerator window. 8GB cards: 8-30. 12GB: 40-60. 24GB: 80+. |
| raft_chunk | INT | 161–64 | Frame-pairs per RAFT forward pass. |
| blend_boundary | BOOLEAN | true | [temporal] Blend the inpaint with original at the crop boundary using stitch_data. |
| remove_quality | COMBO | balanced | [remove] Preset that overrides raft_iter/neighbor_stride/ref_stride/subvideo_length. |
| remove_dilate_pixels | INT | 30–32 | [remove] Dilate the mask by N px before filling to cover anti-aliasing. |
| boundary_band_pixels | INT | 120–96 | [stitch] Width of the boundary band re-painted (0 = no boundary repaint). |
| preserve_inpaint_center | BOOLEAN | true | [stitch] Keep generative inpaint untouched at the centre, only repaint the seam. |
| upscale_method | COMBO | lanczos | [stitch] How to scale the inpainted crop to the canvas region. |
| ring_pixels | INT | 81–64 | [stitch_refine] Half-width of the seam ring in pixels. |
| flow_consistency_thr | FLOAT | 1.500–20 | [flow] Forward/backward consistency threshold (pixels). |
| imagesopt | IMAGE | [temporal/remove] Source frames. | |
| masksopt | MASK | [temporal/remove] Region to inpaint. | |
| stitch_dataopt | STITCH_DATA | [temporal/stitch/stitch_refine] STITCH_DATA from InpaintCropProMEC. | |
| inpainted_imageopt | IMAGE | [stitch] Crop-sized generative inpaint output. | |
| stitched_imageopt | IMAGE | [stitch_refine] Already-stitched canvas image (output of stitch). | |
| mask_overrideopt | MASK | [stitch_refine] Optional explicit canvas-space mask (overrides stitch_data). | |
| frame_aopt | IMAGE | [flow] First frame for optical-flow computation. | |
| frame_bopt | IMAGE | [flow] Second frame for optical-flow computation. | |
| flow_maskopt | MASK | [flow] Optional mask restricting the consistency visualisation. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| image_out | IMAGE | Primary image output (inpainted / filled / stitched / warped per mode). |
| mask_out | MASK | Primary mask output (fill mask / repaint mask / consistency per mode). |
| aux_image | IMAGE | Auxiliary IMAGE (flow_field_rgb in 'flow' mode, zeros otherwise). |
| aux_mask | MASK | Auxiliary MASK (reserved, zeros for now). |
| info | STRING | Info string with timings, coverage, mode-specific stats. |