WanVideo VACE Encode
Where your control video and reference images actually become VACE conditioning
- vae
- input_frames
- ref_images
- input_masks
- prev_vace_embeds
- vace_embeds
VACE is Alibaba's official control framework for Wan - reference-to-video, video extension, and pose- or depth-driven video editing, all from the same underlying model. It's one of the most-used pieces of the entire Wan ecosystem, and this is the node that does the actual work: everything else in a VACE graph (picking which VACE module to load, choosing a preprocessor) exists to feed this one. Your control video, your reference images, your masks - they all funnel through WanVideoVACEEncode and come out as the conditioning your sampler runs against.
If you've used WanVideoVACEModelSelect, this is the node it was setting you up for. Model select happens once, to pick which VACE weights load. This node runs on every generation, encoding what you're actually doing with them.
How it works
You hand it your VAE plus your control inputs - a preprocessed control video (DWPose or depth-mapped), reference images for identity, an inpainting mask, or some combination - and it encodes them into a WANVIDIMAGE_EMBEDS bundle the sampler consumes alongside your text conditioning. strength and the start/end percent pair work like a ControlNet's strength and timing window: how hard VACE's control pushes, and over what slice of the denoising schedule it's active. prev_vace_embeds lets you chain encodes together, which is the building block behind VACE's extension workflows - feed a previous clip's embeds back in so a new segment continues coherently from where the last one left off.
The inputs and outputs that matter
Required, and the ones you'll actually touch:
vae(WANVAE) - needed to encode whatever image/video inputs you supply.width/height/num_frames(defaults 832 × 480 × 81) - your output shape.strength(default 1, 0–10) - how strongly VACE's control applies.vace_start_percent/vace_end_percent(0 to 1, defaults 0 and 1) - the portion of the sampling schedule VACE control is active over.
Optional, and this is where the actual task-specific work happens:
input_frames(IMAGE) - your preprocessed control video, for pose/depth-driven motion.ref_images(IMAGE) - reference images for reference-to-video, keeping identity consistent from a couple of stills.input_masks(MASK) - for video inpainting, restricting edits to specific regions.prev_vace_embeds(WANVIDIMAGE_EMBEDS) - chain a previous encode in, for extension.tiled_vae(default false) - trades speed for lower VRAM during encoding.
Output is a single vace_embeds (WANVIDIMAGE_EMBEDS) into your sampler.
How to install it
Ships with Kijai's WanVideoWrapper. ComfyUI Manager: search ComfyUI-WanVideoWrapper, install, restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-WanVideoWrapper
pip install -r ComfyUI-WanVideoWrapper/requirements.txt
then restart. You'll need a VACE module (1.3B or 14B) selected via WanVideoVACEModelSelect and downloaded into models/diffusion_models, your base Wan model and VAE, plus a preprocessor for whatever control signal you're feeding - DWPose for pose-driven work, a depth estimator for depth-driven work.
Common issues & troubleshooting
It's genuinely slow. VACE 14B generation runs 15–40 minutes on a 4090 at full quality, depending on resolution and frame count. The standard fix is a distillation LoRA like CausVid or lightx2v to cut it to a handful of steps at CFG 1.0 - expect to need one for anything iterative.
14B won't fit. 12GB is pushing it even on fp8; 16GB is where it gets comfortable, and block-swapping is common below that. Step down to the 1.3B module on tighter cards.
The generated video doesn't respect your mask boundary the way you expected. This comes down to which preprocessor fed input_frames. Depth control confines changes to exactly the depth map's boundary - swapping a bikini for a flowing dress often fails because the dress needs to extend outside where the bikini was. DWPose is looser about boundaries. Pick the preprocessor that matches what you're trying to change, not just what's convenient.
Start/end percent set backwards. vace_end_percent needs to be greater than vace_start_percent, same as any timing window - an inverted range effectively turns control off for the whole schedule.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| vae | WANVAE | — | |
| width | INT | 83264–8096 | Width of the image to encode |
| height | INT | 48064–8096 | Height of the image to encode |
| num_frames | INT | 811–10000 | Number of frames to encode |
| strength | FLOAT | 1.0000–10 | — |
| vace_start_percent | FLOAT | 0.000–1 | Start percent of the steps to apply VACE |
| vace_end_percent | FLOAT | 1.000–1 | End percent of the steps to apply VACE |
| input_framesopt | IMAGE | — | |
| ref_imagesopt | IMAGE | — | |
| input_masksopt | MASK | — | |
| prev_vace_embedsopt | WANVIDIMAGE_EMBEDS | — | |
| tiled_vaeopt | BOOLEAN | false | Use tiled VAE encoding for reduced memory use |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| vace_embeds | WANVIDIMAGE_EMBEDS | — |