VACE Control Image Combine
How to mix pose, depth and keyframes in one VACE long video
- control_image
- custom_mask
- previous_control
- vace_control_list
VACE is Wan's control framework, and its superpower is that you can drive one video with several kinds of control at once - pose here, depth there, a keyframe for a specific moment. This node is the pack's glue for that. Each instance takes one control image, pins it to a frame position in the output video, and chains onto the previous controls to build the vace_control_list that the long-video nodes consume.
How it works
You connect one of these per control segment and daisy-chain them via previous_control. The first node in the chain just has its control_image; the second one takes the first's output into previous_control and appends its own. By the time the last one hands the list to SuperUltimate VACE Long Video (or the two-expert variant), the node knows where every control sits in the final video.
The inputs:
control_image- your pose frame, depth map, lineart, keyframe still, whatever VACE is being asked to follow.frame_position- the frame in the final stitched video where this control starts. The node computes the end for you:frame_position + frames - 1 + (repeat - 1).repeat- how many times the control image is reused in a row. Handy for holding a keyframe across several frames instead of loading N copies.masked- whether the control should be treated as masked (only active where the mask says so). Whenmaskedis off, the control is a plain full-frame condition.custom_mask- an optional MASK so the control only applies to part of the frame. When you provide one andmaskedis on, it's used as-is.
Output is vace_control_list (CONTROLIMAGELIST).
The rules it enforces (read these before you wire anything)
The long-video nodes sort your list by frame_position and then run two checks. Get them wrong and the whole run aborts before a single frame is sampled:
- "identical frame_position detected" - two controls starting on the same frame.
- "some control frames overlapped" - two controls whose frame ranges touch. The README is explicit: control frame positions must not repeat or overlap. Different control types can absolutely coexist in one video - that's the whole point - just not on the same frames. Budget the frame positions like a timeline, per segment.
- If the last control's end index runs past the total generated length, you get "Length of control image exceeds length of generation."
Frame positions are measured against the total length the long-video node computes from your prompt chain, so it's worth running Check Total Frame first to know your timeline.
Install
Same pack, same line:
cd ComfyUI/custom_nodes
git clone https://github.com/bbaudio-2025/ComfyUI-SuperUltimateVaceTools
Restart ComfyUI (or Manager → search "SuperUltimateVaceTools").
Gotchas
- The
maskedtoggle andcustom_maskonly do their thing together. Acustom_maskwithmaskedoff is ignored - the source reads it only whenmaskedis true. repeatextends the control's range, which means it extends how much timeline a single control occupies. Three repeats of an 81-frame control eat 243 frames. Plan the positions accordingly.- No model files here - this is pure plumbing on top of your existing VACE setup. The control images themselves (pose/depth preprocessors) are still your job.
It's a fiddly little node, but it's what makes a long video feel directed instead of generated. Set the timeline, respect the overlap rule, and let the long-video node do the rest.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| control_image | IMAGE | — | |
| frame_position | INT | 00–65535 | — |
| masked | BOOLEAN | false | — |
| repeat | INT | 11–65535 | — |
| custom_maskopt | MASK | — | |
| previous_controlopt | CONTROLIMAGELIST | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| vace_control_list | CONTROLIMAGELIST | — |