AP Apply RAFT Optical Flow
The node that actually moves your frame — applying optical flow the way it should work
- images
- flow_data
- warped_images
- valid_mask
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, orrepeat_image.autois the safe pick: if you've wiredcurrent_frame_index, it switches to index-based alignment; otherwise it aligns frame-to-frame.by_indexforces index-based pairing,repeat_imagerepeats the first image against every flow entry. Inauto, the README says index-based behavior is preferred whenevercurrent_frame_indexis 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 swappingflow_directionin most cases; pick one and stay consistent.flow_skipandframes_skip- the offset handles for loop pipelines.flow_skipshifts which flow entry you use,frames_skipshifts 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.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| flow_data | AP_FLOW | — | |
| flow_direction | COMBO | ab | 2 options: ab, ba |
| batch_mode | COMBO | auto | 3 options: auto, by_index, repeat_image |
| flow_skip | INT | 00–2147483647 | — |
| frames_skip | INT | 00–2147483647 | — |
| strength | FLOAT | 1.00-4–4 | — |
| invert_flow | BOOLEAN | false | — |
| interpolation | COMBO | bilinear | 3 options: bilinear, nearest, bicubic |
| padding_mode | COMBO | border | 3 options: border, zeros, reflection |
| current_frame_indexopt | INT | 00–2147483647 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| warped_images | IMAGE | — |
| valid_mask | MASK | — |