Mask Temporal Stabilizer + Integrity
Kill mask flicker on video and catch the frames where tracking broke
- image
- mask
- mask
- integrity_json
- warning
Two separate problems, one node. Mask Temporal Stabilizer (MEC) smooths a per-frame mask sequence so it stops flickering, and it runs an integrity check that flags the exact frames where your mask jumped, shrank, or wandered off. If you've ever rendered a video mask and watched the edge breathe frame to frame, this is the fix.
The situation it's built for: SAM2 or an optical-flow tracker gave you a mask per frame, and the edges jitter - sometimes a 2-pixel wobble you can't see on stills but can't miss in motion, sometimes a full failure where the subject gets re-targeted mid-clip.
How it works
The temporal_mode dropdown picks the stabilizer:
none- passthrough, but you still get the integrity report.gaussian- Gaussian smoothing along the batch dimension, width fromsigma. Cheap, effective on small wobble.raft_flow- RAFT optical-flow-based: warps the previous frame's mask forward and blends withblend(0 = current only, 1 = pure warped-prev). This actually follows motion instead of just blurring over time, at the cost of being heavier.
The integrity check runs in every mode and produces the real gold: per-frame integrity_json with area, centroid, and IoU drift, plus a warning string that names the flagged frame indices. Frames get flagged when the mask drops below drop_threshold in area or IoU (default 0.4) or jumps the centroid by more than jump_threshold (default 0.15, normalized coords). Feed it a mask batch and get back a sentence like "frames 34, 35, 36: area drop" - that's your re-track list.
Outputs: mask (stabilized), integrity_json, warning.
Where it belongs
Use it downstream of MaskTracker's propagate mode, or any SAM2 video pass, as the QA-and-cleanup stage. The workflow: run the tracker → this node → read warning → re-anchor the bad frames (or feed them to the pack's MaskFailureExplainer for a diagnosis). It pairs with MaskAreaProbe too - that one tells you coverage changed, this one tells you where and how. For stills it's pointless; it's strictly a video-batch node.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git
pip install opencv-python>=4.7.0 scipy>=1.10.0
or ComfyUI Manager → search "CustomNodePacks", restart, confirm [MEC] Loaded .... raft_flow mode is the one that may need extra pieces (flow weights auto-download); if it's not installed the gaussian mode still works fine, which is the right way to fail. Start with gaussian + sigma ~1 and read the warning string - most of the value is in the integrity check anyway.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| temporal_mode | COMBO | none | 3 options: none, gaussian, raft_flow |
| blend | FLOAT | 0.500–1 | Mix factor: 1.0 = pure warped-prev, 0.0 = current only. |
| sigma | FLOAT | 1.00–8 | Gaussian sigma (gaussian mode only). |
| device | COMBO | cuda | 2 options: cuda, cpu |
| drop_threshold | FLOAT | 0.400–1 | Area-ratio / IoU below this flags the frame. |
| jump_threshold | FLOAT | 0.150–1 | Centroid jump in normalized coords above this flags the frame. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| integrity_json | STRING | — |
| warning | STRING | — |