Zura Mask
Zura Mask takes any video, not just Wan's — and that's the useful part
- video
- mask_preview
- masked_footage
- mask
Wan 2.2 Animate is a replacement model. It wants a driving clip, a reference identity, a mask saying which pixels get replaced, and pose/face conditioning so it knows how the performer moves. In a stock graph that's a small pile of nodes from Kijai's WanAnimatePreprocess pack wired by hand.
Zura Mask collapses that pile into one node with a dropdown. And unlike most of the pipeline it sits in, its input is a plain VIDEO - so if all you want is a person mask plus a red-tinted debug video, you can use it on any decoded clip from any pack.
Inputs worth knowing
video- anyVIDEOwire. Zura Load Video, someone else's decoder, whatever.replacement_area-Whole character,Whole head, orFace only. This is the one that changes your result most. Whole character replaces head and body; Whole head expands the face landmarks out to hair, forehead and ears, and crucially cuts at the neck so your subject's torso can't wander into the mask; Face only keeps the tight landmark ellipse.mask_expansion- grows the mask by N pixels (default 12). A little slack stops the seam landing on the original silhouette.blockify_mask+block_size- on by default, 32px.
Outputs, and which one goes where
Three outputs, and they are genuinely three different things:
mask_preview- aVIDEOwith the mask tinted red over the footage. Preview it, SaveVideo it, it's a normal video wire. This is your "did the detector actually find the person" check, and you should look at it before spending GPU time.masked_footage- typeZURA_FOOTAGE. This is the payload the sampler consumes, and it's the one non-standard wire in the whole pack. AVIDEOwire can't carry pose, face and mask tensors, so it doesn't try.mask- a nativeMASK. Wire it to ComfyUI's own Preview Mask to see it in isolation, or feed any inpainting node; it isn't Wan-specific.
How it works
Per frame, a YOLOv8-m segmentation model runs on CPU. Deliberate: the diffusion model owns the GPU, and a small segmentation pass must not evict a 14B model's weights. Segmentation (a polygon) rather than bbox detection matters here for the same reason it does in image detailing - a polygon hugs the silhouette, a rectangle leaves edges - and this is the person_yolov8m-seg.pt weight the community has reused for years.
Then the mask is dilated by mask_expansion, blockified, and the pose/face pass runs through the installed WanAnimatePreprocess nodes (OnnxDetectionModelLoader, PoseAndFaceDetection, DrawViTPose) to build the pose video and 512×512 face crops. Face landmark bboxes get a NaN-safe fallback: WanAnimatePreprocess converts landmarks to integers, so an occluded face would otherwise crash there. You get a sane centred crop instead of a traceback.
Blockify is worth a sentence. Wan expects a blocky mask, and the author wanted KJNodes' BlockifyMask behaviour without forcing a KJNodes install: if that node is present the pack calls it, otherwise an internal bounding-box block-grid implementation reproduces the same algorithm. Same output either way - it's a GPL-3.0-derived port, which is why the pack ships AGPL-3.0 with a third-party notice.
One behaviour to respect rather than fight: if detection fails on any frame, the node raises instead of quietly producing a partial mask. "Refusing to continue without a character mask" is the right default - a missing mask halfway through gives you a chunk where the model replaces the background instead of the person.
Install
Manager → Zura Nodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
git clone https://github.com/kijai/ComfyUI-WanAnimatePreprocess
pip install -r ComfyUI_zura_nodes/requirements.txt # into ComfyUI's own python env
Restart ComfyUI afterwards - ultralytics in that requirements file exists for this node.
This node also requires ComfyUI-WanAnimatePreprocess - it supplies the three preprocessing classes above, and without it the node raises with their names in the message.
Model files, in standard ComfyUI model dirs:
ComfyUI/models/ultralytics/segm/person_yolov8m-seg.pt- the segmenter. ComfyUI Impact Subpack's model installer can fetch this one for you.ComfyUI/models/detection/vitpose-l-wholebody.onnx- ViTPose whole-body.ComfyUI/models/detection/yolov10m.onnx- the WanAnimate detector.
The last two are the filenames the preprocessing call asks for by name, loaded from the detection directory that WanAnimatePreprocess registers.
Where people get burned
- Everything is installed and it still says the preprocessing nodes are unavailable. The clone went into a different
custom_nodesfolder, or the pack needs a restart after installing WanAnimatePreprocess. person_yolov8m-seg.ptin the wrong place. It goes undermodels/ultralytics/segm/, not next to the other detection ONNX files. Wrong folder, wrong error.- Occlusion and crowds. The detector is per-frame person segmentation; someone walking through the frame or a face turned away is exactly where it fails, and it fails loudly.
- Cranking
block_sizeormask_expansion"for safety". Big blocks plus big expansion swallows clothing and background, and the model then replaces things you didn't ask it to replace. Defaults (32 / 12) are a sane starting point - changereplacement_areafirst, it's the bigger lever.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | Any video wire: Zura Load Video, or a decoded clip from another pack. | |
| replacement_area | COMBO | Whole character | Whole character: replace head and body. Whole head: replace the entire head including hair and ears. Face only: replace just the face. |
| mask_expansion | INT | 120–128 | Grow the replacement mask by this many pixels before blockifying. |
| blockify_mask | BOOLEAN | true | Quantise the mask to square blocks, as Wan expects. |
| block_size | INT | 328–512 | Size of blocks in pixels (smaller = smaller blocks) — full control, matching KJNodes BlockifyMask. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| mask_preview | VIDEO | — |
| masked_footage | ZURA_FOOTAGE | — |
| mask | MASK | — |