ComfyUI Node

Video Stabilizer

The stabilizer that hands you a mask for the borders it creates

By Code2Collapse·Created 6 months ago·Updated a day ago· 52
Video Stabilizer
  • frames
  • stabilized_frames
  • padding_mask
  • info
methodauto
presethandheld_light
frame_rate16.0
padding_color127, 127, 127
framing_modecrop_and_pad
transform_modesimilarity
camera_lockfalse
strength0.70
smooth0.50
keep_fov0.60
raft_iters12
use_halftrue

Shaky footage is the quiet killer of video-to-video work. Feed a wobbling handheld clip into Wan, an AnimateDiff pass, or an inpaint step and the shake turns into motion blur, doubled edges, and seams that track nothing. So you reach for a stabilizer - and immediately hit the classic problem: stabilizing means re-framing, and re-framing crops into your shot. You lose FOV, and on a video you can't just "zoom out" to get it back.

The clever part of this node is that it solves that second problem for you. It wraps the MIT-licensed ComfyUI-Video-Stabilizer by nomadoor - the one from the well-received "stabilize without narrowing FOV" workflow that made the rounds on r/StableDiffusion - and adds an output the upstream had to be asked for: a padding mask that tells you exactly where the stabilizer introduced empty borders. Wire that mask into an inpaint pass and you can repaint the missing frame instead of losing it.

How it works

Three backends, one dropdown:

  • classic - sparse GFTT feature tracking + Lucas-Kanade optical flow, runs on CPU, fast, needs well-textured footage.
  • raft_flow - dense RAFT optical flow on GPU. Slower, but robust on texture-poor plates where feature tracking falls apart: snow, sky, water, out-of-focus shots.
  • auto - picks raft_flow when CUDA has ≥4 GB free and you feed it more than 24 frames, otherwise classic.

Whichever backend runs, the pipeline is the same shape: estimate the camera path, fit a transform to it, smooth that path over time, then reconstruct the frames - filling whatever the original didn't cover with your padding_color and reporting that coverage as a mask. The parameter names follow DaVinci Resolve conventions, so they read intuitively if you've touched a Resolve stabilizer.

The inputs that matter

You'll mostly live on preset and leave the rest alone - a preset overrides the manual sliders unless you set it to manual:

  • preset - handheld_light (default), handheld_heavy, vehicle, tripod_lock, or manual. Good starting points for action-cam shake, drone footage, or a locked-off plate.
  • framing_mode - crop zooms in to absorb shake, crop_and_pad keeps the zoom modest and fills the spill, expand pads without cropping. crop is where the FOV loss comes from.
  • transform_mode - translation, similarity (default), or perspective. Step up to perspective when the camera is actually rolling, not just bobbing.
  • frame_rate - set this near your source's real FPS. Smoothing is time-based, so a wrong FPS makes the wobble comeback; this bit the upstream author on 120 fps footage before the explicit FPS parameter existed.
  • raft_iters and use_half - only matter for raft_flow. More iterations = better flow, half precision = less VRAM.

Outputs and where they go

Three outputs: stabilized_frames (IMAGE), padding_mask (MASK), and an info string with the picked backend and timings. The padding_mask is the reason this node is worth reaching for over a plain stabilizer. It's 1 where the original frame didn't cover the canvas - i.e. the borders you need to fill. The pack's own pattern is:

stabilized_frames ──► InpaintCropProMEC (image)
padding_mask     ──► InpaintCropProMEC (mask)  → inpaint → stitch

Or feed the mask into a VACE outpainting pass on Wan, which is exactly the "keep your FOV while stabilizing" trick the upstream workflow thread demonstrated.

Install

It's part of the umbrella ComfyUI-CustomNodePacks pack, so install that and you get this node plus a few dozen masking/inpaint tools under the same roof:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

Or ComfyUI Manager → search "CustomNodePacks" → install, then restart. The pack's requirements.txt wants opencv-python and scipy - check what you already have before blindly pip install -r requirements.txt, because ComfyUI bundles its own torch/numpy and the README explicitly warns against clobbering them. Classic stabilization needs no model download.

Common issues

  • "ComfyUI-Video-Stabilizer not vendored or import failed" - the node loads the upstream from third_party/ComfyUI-Video-Stabilizer/, which the repo gitignores - if it didn't land with your clone, drop a checkout of the upstream repo in there.
  • Flow backend missing - if RAFT isn't available (HAS_FLOW=false), auto and raft_flow silently fall back to classic and log a warning. Classic still works; for flow, follow the upstream's weight instructions.
  • Edges flap or wobble - you've over-stabilized. Drop strength from 1.0 to 0.7–0.85.
  • Unwanted zoom-in - you're on crop. Switch to crop_and_pad and inpaint the padding_mask.
  • OOM on the flow backend - fewer frames, keep use_half on, or fall back to classic.

One honest caveat: this is a young node from a young pack - the repo moves fast and the README lags the code. The tooltips and the auto-generated node reference are more current than the marketing prose. But the core idea - stabilize, then repair the damage instead of cropping it away - is solid, and it's the rare stabilizer that treats the FOV problem as a first-class citizen.

CategoryC2C/Stabilization

Inputs (13)

NameTypeDefaultDescription
framesIMAGE
methodCOMBOauto3 options: auto, classic, raft_flow
presetCOMBOhandheld_lightPreset overrides the manual widgets below unless set to 'manual'.
frame_rateFLOAT16.0
padding_colorSTRING127, 127, 127
framing_modeCOMBOcrop_and_pad3 options: crop, crop_and_pad, expand
transform_modeCOMBOsimilarity3 options: translation, similarity, perspective
camera_lockBOOLEANfalse
strengthFLOAT0.700–1
smoothFLOAT0.500–1
keep_fovFLOAT0.600–1
raft_itersINT124–32RAFT iterations. Used only by method=raft_flow (and auto when it picks flow).
use_halfBOOLEANtruefp16 for RAFT. Used only by method=raft_flow.

Outputs (3)

NameTypeDescription
stabilized_framesIMAGE
padding_maskMASK
infoSTRING