Nodes/ComfyUI-Video-Stabilizer/Video Stabilizer Flow
ComfyUI Node

Video Stabilizer Flow

Dense optical flow stabilization

By nomadoor·Created 10 months ago·Updated 2 months ago· 89
Video Stabilizer Flow
  • frames
  • padding_color
  • Stabilized Frames
  • Padding Mask
  • Motion Meta
frame_rate16.0
framing_modecrop_and_pad
transform_modesimilarity
camera_lockfalse
strength0.70
smooth0.50
keep_fov0.60

If Video Stabilizer Classic is the pack's quick-and-cheap option, this is the "actually try this one first" option. Video Stabilizer Flow does the same job - estimate the camera motion between frames, smooth it, warp the frames to cancel the jitter - but it measures the motion with dense optical flow instead of tracking a few hundred corner points. Every pixel gets a vote, not just the textured ones.

The author is blunt about it in the README: unless processing speed is a real concern, Flow is the safe default. Corner tracking needs texture to grab onto; dense flow doesn't care, so Flow keeps working on scenes where Classic quietly gives up - smooth gradients, featureless walls, soft-focus bokeh. The cost is CPU time, and it's a real cost, though still nothing next to the GPU time a video generation pass eats.

How it works

The node computes a per-pixel motion field between consecutive frames, then fits a geometric transform to that field and smooths the resulting camera path over time, exactly like Classic does downstream. The interesting part is the backend selection, because it fails gracefully:

  • DIS (Dense Inverse Search) is the default - OpenCV's fast dense flow.
  • TV-L1 kicks in as a fallback if DIS is unavailable, when the cv2.optflow contrib module is present.
  • Phase correlation is the last resort, a translation-only estimate that keeps the node alive rather than crashing.

That "prefer a degraded estimate over an error" attitude runs through the whole pack, and it's worth knowing about: a scene that defeats flow won't hard-fail, it'll silently fall back to something weaker.

The author benchmarked 300 frames of 1080p at 30 fps on an i9-10900F at about 85 seconds. Your mileage varies, but that's the ballpark - comfortable for short clips, something to think twice about for a 10,000-frame batch.

The inputs that matter

The schema is the same public surface as Classic, so if you've used one, you've used the other:

  • frames - video or image batch.
  • strength - removal gain: 0 keeps original motion, 1 removes it based on the smoothed curve. Default 0.7.
  • smooth - how strongly the motion curve is smoothed before removal. Higher = slower, more sweeping result.
  • framing_mode - crop (zoom to hide borders), crop_and_pad (modest zoom + padding), expand (grow the canvas).
  • camera_lock - a boolean that pushes aggressively toward a locked tripod-like solution, used instead of strength/smooth.

frame_rate scales the smoothing window - set it to your real fps, not the default 16, or high-fps footage will come out barely touched (a classic-pack issue that was fixed by adding this parameter). keep_fov only applies in crop mode, and transform_mode (translation/similarity/perspective) picks the geometric model fitted to the flow.

Outputs

  • Stabilized Frames (IMAGE) - the result; send it to a video combine node.
  • Padding Mask (MASK) - the exposed edges, ready for VACE outpainting so you can stabilize without narrowing the field of view. The pack ships Wan2.1 and Wan2.2 VACE example workflows built around this.
  • Motion Meta (JSON) - the removed camera motion, recorded so you can restore it later or transfer it onto regenerated frames with Video Stabilizer Motion Apply.

Install and gotchas

Same as the rest of the pack: ComfyUI Manager → search "ComfyUI-Video-Stabilizer", or:

cd ComfyUI/custom_nodes
git clone https://github.com/nomadoor/ComfyUI-Video-Stabilizer

Restart, done. No models to download; the only dependency is opencv-python-headless. It does need a recent ComfyUI because the pack uses the newer V3 node API - if the node is missing, update ComfyUI before you debug anything else.

Two practical warnings. First, TV-L1 depends on cv2.optflow, which isn't guaranteed on every OpenCV build - if DIS is missing too, you'll quietly end up on phase correlation, which only handles translation. Second, expand mode with camera_lock on can make the output canvas grow dramatically as it absorbs the full shake as padding. For long clips on a modest CPU, that's the difference between a coffee break and a lunch break.

CategoryVideo/Stabilization

Inputs (9)

NameTypeDefaultDescription
framesIMAGE
frame_rateFLOAT16.0Frame rate in frames per second used to scale smoothing window.
framing_modeCOMBOcrop_and_padChoose how borders produced by stabilization are handled.
transform_modeCOMBOsimilaritySelect the geometric model fitted to the optical flow.
camera_lockBOOLEANfalseAggressively pull the motion curve toward a locked tripod-like solution.
strengthFLOAT0.700–1Removal gain (0 keeps original motion, 1 removes it using the smoothed motion curve).
smoothFLOAT0.500–1Temporal smoothing amount applied to the motion curve before removal.
keep_fovFLOAT0.600–1[Crop only] How much of the original FOV to preserve (1.0 = no zoom, 0.0 = maximum zoom). Ignored when framing_mode is crop_and_pad or expand.
padding_colorCOLOR#7F7F7FHEX padding color applied in crop_and_pad / expand (e.g. #404040).

Outputs (3)

NameTypeDescription
Stabilized FramesIMAGE
Padding MaskMASK
Motion MetaJSON