CS VideoMaMa
Your mask has no soft edges, and this is the node that gives it some
- image
- mask
- MASK
Segmentation and matting are different jobs, and the whole background-removal argument of the last two years comes down to people mixing them up. SAM, SAM3, BiRefNet - anything with "segment" in the name - labels each pixel foreground or background, which is structurally incapable of representing one hair at 40% opacity. Matting predicts fractional alpha, and fractional alpha is the only output type that survives being composited onto a new colour.
Do that in video and you get a second problem: per-frame matting flickers. Frame 100's hair strands do not agree with frame 101's, and the mask boils.
CS VideoMaMa is the video-native answer to both. You hand it a rough, chunky, binary-ish per-frame mask - the kind SAM3.1 or a brush gives you in two minutes - and it returns a soft 8-bit temporal alpha matte that holds together across the whole clip. If your subject is a person, look at CS MatAnyone2 in the same pack too - the community signal for person rotoscoping leans that way, and MatAnyone is the name people actually type. VideoMaMa doesn't care what the subject is, which is exactly why it's worth having.
How it works
VideoMaMa is a single-step Stable-Video-Diffusion UNet fine-tuned to take frames plus a coarse mask and output alpha. No sampler, no prompt, no CFG, one forward pass per batch. The CineStyle node is built on the inference pipeline used by Sammie-Roto 2, and that fork never loads the SVD CLIP image encoder at all - upstream code only loads it in order to zero its output away, so skipping it is free.
Three details do the heavy lifting:
It batches by your free VRAM, not by your clip length. Temporal attention in that SVD UNet grows faster than linearly with frame count, so a whole clip OOMs long before a 24 GB card is full. One pass covers as many frames as fit at the current working size; long clips become several passes.
The pass seams are fed back, not just blended. The seam frames of each pass are re-predicted using the previous pass's own soft output as conditioning, then cross-faded. That feedback is why batch_overlap of 2 is genuinely enough - set it to 0 and you get neither the feedback nor the blend, and the seams are visible.
Inference runs inside the union bounding box of the masks, padded by 10% (minimum 32 px) and snapped outward to a multiple of 8. A subject filling a third of a 1080p frame costs a third of the pixels, which is what lets a pass cover more frames on the same card. And if the box covers more than 90% of the frame anyway, the node skips the crop rather than change your aspect ratio for nothing.
Also worth knowing: frames that are entirely empty or entirely full never reach the model - they come out as exact 0 or 1 - and if the VRAM estimate turns out optimistic, the node clears the cache, halves the pass length and restarts the run from the top of the clip, twice before giving up.
Inputs, and the one that matters
image and mask are the pair, and the mask is binarised at 0.5, so any feathering or blur you applied upstream is discarded before inference. Don't pre-soften it; if anything, grow it with CS Mask Grow so the model has room to find the real edge. A single mask broadcasts to every frame - handy for a static subject, useless for anything moving.
Then the knobs, in order of how much you'll care:
max_resolution(default1280, "Max working resolution") - a cap on the size of the region actually fed to the model, and the main speed lever, since pixel count decides how many frames fit in one pass. Output always comes back at source resolution. Crunchy edges? Raise it. Clip taking forever? Lower it.motion_bucket_id(default127) - SVD's motion conditioning, which is not your clip's real motion. Leave it alone unless edges flicker, in which case try 50–100.seed(default42) - drives both the UNet noise and the VAE posterior sample, so the same seed reproduces a clip bit for bit. The global RNG is snapshotted and restored, so it won't reshuffle seeds elsewhere in your graph.batch_overlap(default2) - see above. It's capped at half the pass length, because a seam wider than half a pass re-predicts more than it advances.cpu_offloadandforce_unload_model- both default off. The second one is the one to flip when you're alternating with a big video model; ComfyUI doesn't track these diffusers modules, so nothing else will hand the VRAM back for you.
There's exactly one output: MASK. Frame count, order and resolution match your input exactly - nothing padded, trimmed or reordered. Wire it into CS Image Composite as layer_mask (white shows the layer) with your original plate as the background.
Install and the ~6 GB of weights
Manager → search ComfyUI_CineStyle, or:
cd ComfyUI/custom_nodes
git clone https://github.com/chflame163/ComfyUI_CineStyle.git
# restart ComfyUI
Nodes appear under 😺dzNodes/CineStyle. The pack's requirements.txt needs diffusers>=0.34.0 on top of the usual transformers/peft/accelerate/opencv/hydra-core stack, so give the install a clean environment and a restart before you blame the node.
First run fetches four MD5-verified files into ComfyUI/models/videomama/, about 6 GB total: the UNet from SammyLim/VideoMaMa and the fp16 VAE from stabilityai/stable-video-diffusion-img2vid-xt. VIDEOMAMA_MODEL_DIR moves the folder; VIDEOMAMA_HF_ENDPOINT or plain HF_ENDPOINT sets a mirror for a slow or blocked Hugging Face. If the download dies, grab the files manually - a bad MD5 just triggers another download, it won't silently load garbage.
Gotchas
A feathered input mask does nothing. Already covered, but it's the mistake everyone makes once.
Licensing, if you're shipping. The pack is MIT, but VideoMaMa's weights and the SVD base carry their own upstream licenses - commercial use or redistribution means reading both. And set your expectations on obscure: across two years of r/StableDiffusion and r/comfyui threads, VideoMaMa is named roughly once. That isn't a quality verdict, it's a tool that lives inside rotoscoping pipelines rather than in demo posts, so if you go looking for a crowd-tested thread of settings, you'll be the one writing it.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| device | COMBO | auto | auto follows whatever device ComfyUI is currently using. |
| seed | INT | 420–18446744073709550000 | Drives both the UNet noise and the VAE posterior sample, so the same seed reproduces a clip bit for bit. The global RNG is snapshotted and restored, so other nodes in the workflow are unaffected. |
| image | IMAGE | Video frames as a ComfyUI IMAGE batch. | |
| mask | MASK | Matched per-frame coarse masks; one shared mask broadcasts to every frame. Binarised at 0.5, so feathered edges are discarded. | |
| batch_overlap | INT | 20–32 | Frames two consecutive passes share. They are re-predicted from the previous pass's soft alpha, then cross-faded; 2 is enough because of that feedback. 0 disables both and leaves visible seams. Capped at half the pass length: a wider seam re-predicts more than half of every pass, which costs more than it buys. |
| max_resolution | INT | 1280256–2048 | Cap on the longest side of the region actually fed to the model. This is the main speed control, since pixel count decides how many frames fit in one pass. Output always returns to the source resolution. |
| motion_bucket_id | INT | 1271–255 | SVD motion conditioning, not the clip's real motion. Lower (50-100) = subtle, higher (150-200) = dynamic. Leave at 127 unless edges flicker. |
| cpu_offload | BOOLEAN | false | Keep weights in RAM and move them per stage. Saves VRAM but costs a transfer per pass, a poor trade once a clip needs many passes. |
| force_unload_model | BOOLEAN | false | Release the models when this run ends so other nodes can take the VRAM back. ComfyUI does not track these diffusers modules by itself. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |