ComfyUI Node

AP Apply RAFT Optical Flow

The node that actually moves your frame — applying optical flow the way it should work

By adampolczynski·Created 6 months ago·Updated 6 months ago· 1
AP Apply RAFT Optical Flow
  • images
  • flow_data
  • warped_images
  • valid_mask
flow_directionab
batch_modeauto
flow_skip0
frames_skip0
strength1.00
invert_flowfalse
interpolationbilinear
padding_modeborder
current_frame_index0

So you've computed flow with APGetRAFTOpticalFlow - now you need to actually warp a frame along those motion vectors. That's this node's whole job: it takes an image (or a batch of images), pushes it through the flow field, and outputs the warped result plus a valid_mask telling you which pixels actually had valid motion to warp with.

This is the node you reach for in the classic temporal-consistency pattern. You've got a video. You don't want every frame to be a fresh roll of the dice, because then the scene shimmers and the background crawls. So you warp the previous frame forward along the flow into the next frame's position, feed that into your sampler as the new start, and let diffusion only fix what the warp couldn't. That's the same idea as WarpFusion and every flow-warping workflow since - this pack just gives you a version that doesn't fall over in a real ComfyUI graph.

The mechanism

Under the hood it's a grid-sample warp: the flow field tells it, for each output pixel, where to look in the source image, and interpolation (bilinear/nearest/bicubic) decides how to sample. padding_mode (border/zeros/reflection) governs what happens at the image edges where the warp pulls in data from outside the frame - border is the sensible default, zeros leaves black edges. The valid_mask output is the flip side of that: it's 1 where the warp had real source data and 0 (or lower) at the boundaries, and you should treat it as a first-class output. Blend warped and unwarped pixels based on it, or you'll get black smears at the frame edge.

The inputs that matter

The plumbing trio on every flow node in this pack is flow_direction, batch_mode, and the skip counters, and they're the difference between "this works" and "this works when I'm iterating over a video."

  • flow_direction (ab/ba) - which way to push the image. If motion looks reversed, flip this. The author's own note: flow direction matters, and reversing is expected.
  • batch_mode - auto (default), by_index, or repeat_image. auto is the safe pick: if you've wired current_frame_index, it switches to index-based alignment; otherwise it aligns frame-to-frame. by_index forces index-based pairing, repeat_image repeats the first image against every flow entry. In auto, the README says index-based behavior is preferred whenever current_frame_index is connected.
  • strength - multiplies the flow before warping. 1.0 is "exactly where motion says"; less is a partial warp. Go under 1.0 when you want the diffusion model to have room to do its own thing on top.
  • invert_flow - flips the sign of the field. Same effect as swapping flow_direction in most cases; pick one and stay consistent.
  • flow_skip and frames_skip - the offset handles for loop pipelines. flow_skip shifts which flow entry you use, frames_skip shifts where in the frame sequence you start. These exist because loops often begin mid-sequence or want delayed flow activation.

The optional current_frame_index is where APIndexer plugs in. Feed it the persistent frame counter and the node can align a multi-entry flow batch to the exact frame you're on - which is the whole point of the pack's index-aware design.

Outputs

warped_images is your motion-aligned frame - feed it into a sampler or a VAEEncode as the starting point. valid_mask is the MASK you'll want downstream for any compositing, so you don't let invalid warp regions bleed into the result.

Installing it

Same as the rest of the pack - ComfyUI Manager (search "AP_OpticalFlow"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/adampolczynski/ComfyUI_AP_OpticalFlow
python -m pip install -r custom_nodes/ComfyUI_AP_OpticalFlow/requirements.txt

Then restart. Only real dependency is torchvision>=0.15 (the RAFT weights auto-download on first flow compute, not here).

The trap to watch

The plain APApplyRAFTOpticalFlow warps the whole frame, background included. If you're doing temporal warping for an inpaint pipeline, that's usually wrong - you want the warp confined to the region that actually moved, and untouched background left alone. That's what the masked variant (APApplyRAFTOpticalFlowMasked) is for, and the README's recommended setup routes warped_mask from that node into APFlowComposite.effect_mask with use_difference_gate=true. If you find warped results smearing your background, you skipped the masked step, not the warp itself.

CategoryAP_OpticalFlow

Inputs (11)

NameTypeDefaultDescription
imagesIMAGE
flow_dataAP_FLOW
flow_directionCOMBOab2 options: ab, ba
batch_modeCOMBOauto3 options: auto, by_index, repeat_image
flow_skipINT00–2147483647
frames_skipINT00–2147483647
strengthFLOAT1.00-4–4
invert_flowBOOLEANfalse
interpolationCOMBObilinear3 options: bilinear, nearest, bicubic
padding_modeCOMBOborder3 options: border, zeros, reflection
current_frame_indexoptINT00–2147483647

Outputs (2)

NameTypeDescription
warped_imagesIMAGE
valid_maskMASK