Nodes/ComfyUI-WanVaceAdvanced/WanMaskToLatentSpace
ComfyUI Node

WanMaskToLatentSpace

Get masks onto Wan's latent grid without the blur

By drozbay·Created about a year ago·Updated 7 months ago· 95
WanMaskToLatentSpace
  • mask
  • mask
spatial_methodmax
temporal_methodmax
first_frame_specialtrue
target_width0
target_height0
expand_spatial0
expand_temporal0

Most mask→latent conversions in ComfyUI just run a VaeEncode-style pass and call it a day. Wan is the awkward one: its 3D causal VAE compresses space by 8× and time by 4×, so a pixel-space mask doesn't line up with the latent grid unless you downscale it the same way - and a naive bilinear downscale smears thin fast-moving mask regions into soft mush. That's the problem WanMaskToLatentSpace is built for, and it's why the pack's context-window workflow highlights this node: hard-edged masks stay hard-edged on the latent grid.

What it does

It takes a pixel-space mask and reduces it to Wan's latent shape: H×W ÷ 8 spatially, and frames grouped by 4 temporally (with the first frame kept 1:1 - Wan's first latent frame maps to a single video frame, the rest map to groups of 4). Crucially, the reduction method is yours to pick, because "which pixels survive" changes the mask's meaning:

  • Spatial (spatial_method): max keeps a latent cell if any pixel in it was masked (preserves coverage - the default); min requires full coverage; mean averages; area and nearest are resizing shortcuts with slightly different edge behavior.
  • Temporal (temporal_method): across each 4-frame group - max/min/mean, or just take first/last.

So for a character bounding box you probably want max/max so the mask never loses a finger; for a soft region you might prefer mean/mean. The defaults (max/max) are the safe starting point.

The inputs that matter

  • mask (MASK) - your pixel-space mask, can be 2D (single frame), 3D, or a [B,T,H,W] batch.
  • spatial_method / temporal_method - the two enums above.
  • first_frame_special (default on) - true keeps frame 0 at 1:1, everything else grouped by 4; off groups all frames uniformly.
  • target_width / target_height - 0 = auto (mask ÷ 8); set them if your latent is a non-divisible size.
  • expand_spatial / expand_temporal - grow (+) or shrink (−) the mask in pixels/frames before downscaling, using morphological dilation/erosion. Positive spatial expansion is the standard trick for a mask that needs to hug its subject with a safety margin.

Output is a single mask in latent space, ready to feed straight into a VACE control-mask input or a SetLatentNoiseMask for continuation work.

Where it fits

Two realistic spots. First, in front of any VACE node's control_masks input when your control video's masks are noisy or fast-moving - the README specifically calls out avoiding "trilinear blur on fast-motion masks before they flow through the windows." Second, as a preprocessing step before context-window slicing, so masks stay aligned with latent frames when WanContextWindowsManual reorders them.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/drozbay/ComfyUI-WanVaceAdvanced
# restart ComfyUI

or ComfyUI Manager → "ComfyUI-WanVaceAdvanced". The pack's only real pip dependency is scipy, which is what the morphological expansion uses. If your mask comes back visibly shifted or shrunk, check your target_width/height against your actual latent size - auto (÷8) is right for standard 832×480→104×60, but the moment your latent is padded to a multiple the auto math drifts. It's a small node, but it's the difference between masks that hold their shape through a generation and masks that bleed.

CategoryWanVaceAdvanced

Inputs (8)

NameTypeDefaultDescription
maskMASK
spatial_methodCOMBOmaxSpatial reduction: max=preserve any coverage, min=require full coverage, mean=average, area=area-based, nearest=nearest-exact
temporal_methodCOMBOmaxTemporal reduction: max/min/mean across 4-frame groups, or first/last frame only
first_frame_specialoptBOOLEANtrueTrue: first frame 1:1, rest grouped by 4. False: all frames grouped by 4 uniformly.
target_widthoptINT00–16384Target latent width. 0 = auto (mask width / 8)
target_heightoptINT00–16384Target latent height. 0 = auto (mask height / 8)
expand_spatialoptINT0-16384–16384Pixels to grow (+) or shrink (-) spatially before downscaling
expand_temporaloptINT0-1000–1000Frames to grow (+) or shrink (-) temporally before downscaling

Outputs (1)

NameTypeDescription
maskMASK