๐ Pixel Hold
The flicker suppressor that locks your background down
- frames
- reference
- images
- mask_preview
Every local video generator has the same tell: flat areas shimmer. Backgrounds, walls, skies - regions the model decided were "smooth" come out with a micro-flicker frame to frame, and once you see it you can't unsee it. Pixel Hold is the node that cleans that up. It locks each frame's stable regions to a chosen reference - an external image, or a frame from the clip itself - and only lets pixels change when the change is big enough to be real motion. Small fluctuations get pinned; actual movement passes through untouched.
The author's description is precise: it reduces "micro-flicker/static shimmer sometimes introduced by diffusion." And it has a creative second life, because the reference doesn't have to be the clip - hand it an external image and it'll hold everything in the frame that isn't moving to that image. That's the difference between "clean up the flicker" and "make the static background a specific picture."
How it works
For each frame, the node measures how much changed relative to the reference, region by region, and builds a mask of "changed enough to matter." Pixels under the mask keep their new values; everything else gets held at the reference. The sensitivity machinery is what makes it usable:
- auto_luma (on by default) adapts the brightness threshold per frame, so it doesn't need hand-tuning per clip.
auto_k(default 2.5) sets how aggressively it locks - 2โ3 is the typical range. - mode -
tile(default) measures change in blocks (fast and robust),pixeldoes it per-pixel (finer, noisier). - edge_band - protects a belt around strong edges so the lock doesn't create wobbly, stretchy boundaries where motion meets static regions. This is the setting that keeps hard edges from smearing.
- apply - hold the whole image (
all) or only its low-frequency part (lowfreq), which is a lighter touch for videos that just need the flat areas steadied. - linearize (on by default) works in linear color for steadier results on flat areas.
- dilate / feather_sigma - expand and soften the mask edges so the hold blends in instead of leaving a hard seam.
- process_on - auto/CPU/GPU. Auto pushes to GPU for very large frames;
gpu_clear_everyfrees VRAM every N frames if you're running long clips.
The inputs and outputs
- frames - your clip.
- ref_source -
external(use thereferenceimage) orbatch_index(use frameref_indexof the clip as the reference). External references get resized to match if sizes differ. - images (output) - the stabilized clip.
- mask_preview (output) - an IMAGE of the hold mask, so you can see exactly what got locked and what passed through. Wire this to a preview node while tuning.
Installing it
WhiteRabbit pack, one-time install:
cd ComfyUI/custom_nodes
git clone https://github.com/Artificial-Sweetener/comfyui-WhiteRabbit
cd comfyui-WhiteRabbit
python -m pip install -r requirements.txt
or ComfyUI Manager โ "WhiteRabbit". The pack's only pip dependency is torchlanc; it targets ComfyUI's v3 node API, so keep ComfyUI updated.
Where people get burned
- Locking everything. If the mask preview shows almost the whole frame held, your thresholds are too loose (or the clip genuinely has no motion). Check
mask_previewfirst - that's what it's for. - Expecting it to fix moving backgrounds. It holds static regions. A panning camera means nothing is static, and the node can't invent stillness.
- Using it after compression artifacts are baked in. It reduces shimmer; it won't un-blur a compressed sky. Run it on the cleanest version of the clip you have.
Run it as a post pass before encoding and the difference is the difference between "AI video" and "finished video." The flicker is the giveaway every time.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| frames | IMAGE | Your clip (framesรHรWรC, values 0โ1). | |
| ref_source | COMBO | external | Pick the reference: an external image or a frame from this clip. |
| ref_index | INT | 00โ999999 | If using a frame from this clip, which frame to use as the reference. |
| linearize | BOOLEAN | true | Work in linear color for steadier results on flat areas. |
| auto_luma | BOOLEAN | true | Auto sensitivity for brightness changes (adapts per frame). |
| auto_k | FLOAT | 2.50.5โ6 | Auto strength. Higher = lock more to the reference (2โ3 is typical). |
| tau_luma | FLOAT | 0.00590โ0.01568627450980392 | Manual brightness threshold when Auto is OFF. Lower = stricter (more locking). |
| tau_grad | FLOAT | 0.0200โ1 | How much edge change to allow. Lower protects edges more. |
| mode | COMBO | tile | Tile: fast & robust. Pixel: finer but noisier. |
| tile_size | INT | 328โ256 | Tile size when using Tile mode. |
| score_mode | COMBO | l1_tile | How tiles measure change: mean abs diff (fast) or median abs dev (robust). |
| edge_band | BOOLEAN | true | Protect a belt around strong edges to avoid wobble/stretch. |
| band_radius | INT | 40โ64 | Width of the protected belt (pixels). |
| tau_edge_low | FLOAT | 0.00590โ0.25 | Treat as low-motion below this level (edge belt). |
| tau_edge_high | FLOAT | 0.02350โ0.5 | Treat as high-motion above this level (edge belt). |
| apply | COMBO | all | Hold the whole image (All) or only its smooth part (Low-freq). |
| dilate | INT | 10โ16 | Expand the mask (pixels). |
| feather_sigma | FLOAT | 2.00โ16 | Soften mask edges (pixels). |
| process_on | COMBO | auto | Choose CPU/GPU. Auto switches to GPU on very large frames. |
| gpu_clear_every | INT | 00โ1000 | If >0 and using GPU, free memory every N frames. |
| referenceopt | IMAGE | Optional external reference (1รHรWรC). If sizes differ, it will be resized to match. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | โ |
| mask_preview | IMAGE | โ |