Nodes/Link Comfy Nodes/Stabilize Frames
ComfyUI Node

Stabilize Frames

Turning AI wobble into a game-ready sprite loop

By Mister-Link·Created 10 months ago·Updated 3 days ago· 0
Stabilize Frames
  • image
  • mask
  • frames
  • masks
  • stabilization_metadata

Stabilize Frames is the node that makes AI-generated animation usable as game art. If you've ever generated a looping animation of a character and tried to drop it into a game, you know the problem: the character isn't actually still. The whole body drifts a few pixels left, then right, then up - diffusion models don't know what a tripod is. This node takes your frames plus a mask of the foreground, cancels out that global drift so the character stays locked in place across the loop, crops everything to a tight bounding box, and hands you the motion data so the game can put the movement back. It's the missing link in a very specific but very real pipeline: generate a loop → Stabilize Frames → Pixelate → Spritesheet Builder → export.

The context: people absolutely do make game sprites with ComfyUI, and it's famously fiddly. The community routes around the consistency problem with ControlNet poses, 3D-model renders, and sprite-sheet workflow templates - the stubborn remainder is frame alignment, which is exactly what this node fixes. It slots into the rest of this pack (Spritesheet Builder consumes its metadata directly).

How it works

Under the hood it's classic computer vision, not a model. For each frame it extracts the foreground alpha from your mask, scales everything to a reference canvas, then estimates the offset between adjacent frames with cv2.phaseCorrelate - phase correlation, the image-registration workhorse. It's global and feature-independent: it aligns the whole image, not a specific body part.

Two details make it clever:

  • It assumes a loop. Pairwise shifts are computed around the full cycle (last frame wraps to the first), and it subtracts the median position so the net drift over the whole animation is zero. A perfect loop in, a stable loop out.
  • It doesn't destroy the motion. Every correction is recorded as a per-frame motionOffset, and the output metadata carries the source size, pivot, and per-frame offsets in a JSON manifest (format link-comfy-nodes/stabilization-v1). The game engine adds that displacement back after pixelization and trimming.

Inputs and outputs

Only two inputs, both required:

  • image - your frame batch (IMAGE). A looping animation, ideally from a video or frame-sequence node.
  • mask - the foreground mask (MASK). It's clever about shapes: one single mask gets repeated across all frames, and a per-frame mask batch works too. It must match the frame count and frame size, or the node raises a clear error rather than silently mangling things.

Three outputs:

  • frames (IMAGE) - the stabilized, cropped frames, aligned and trimmed to the union of all the foreground masks.
  • masks (MASK) - the matching per-frame alpha masks for the corrected frames.
  • stabilization_metadata (STRING) - the JSON manifest with sourceSize, pivot, and per-frame spriteSourceSize + motionOffset. Feed this straight into the pack's Spritesheet Builder for the full game-asset workflow.

Installing it

It ships in Link Comfy Nodes (a whole pack, not a single node):

  • Easiest: ComfyUI Manager → search "Link Comfy Nodes" → Install → restart.
  • Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/Mister-Link/link-comfy-nodes
cd link-comfy-nodes
pip install -r requirements.txt
# restart ComfyUI

The pack's requirements.txt is heavy - torch, opencv-python, transformers, scikit-learn, numba, and more, shared with its other nodes (matting, pixel art, video). ComfyUI gives you no per-node isolation, so all of that lands in your shared Python environment (see the ecosystem doc for why that's the standing complaint). Installing a pack to use one node is normal here.

Where people get burned

  • The mask has to actually cover the moving thing. Empty or blank masks trigger "Registration moved all frames outside their canvas" - the code can't find a foreground to anchor on. Feed it a decent subject mask (this pack even ships matting models used elsewhere for that).
  • It wants a loop. It's built for cyclic animation. Throw a one-shot clip or footage with big scene cuts at it and the wrap-around registration will fight you. This is a sprite-animation stabilizer, not a shaky-video smoother.
  • Frame/size mismatches error out, loudly and clearly (Frame count mismatch, Frame size mismatch). That's a feature: it refuses to silently corrupt your sprites.

One last thing to internalize: the pack's README is literally "AI slop nodes for my own purposes, use at your own risk (I change how nodes behave without warning)." It's a personal pack from a dev who ships what he needs, and it's genuinely useful - just don't treat it as a stable dependency, and pin the version if you're building a workflow you'll reuse. For the niche it targets - stable, game-ready sprite loops out of a diffusion model - nothing else in the ecosystem does quite this job.

CategoryImage/Animation

Inputs (2)

NameTypeDefaultDescription
imageIMAGE
maskMASK

Outputs (3)

NameTypeDescription
framesIMAGE
masksMASK
stabilization_metadataSTRING