Wan Vace Keyframe Builder
The VACE Keyframe Composer That Fixed What Kijai's Node Made Painful
- background_images
- image_1
- images
- masks
If you've used Wan VACE for inbetweening - anchoring a video with reference frames you want the model to hit exactly - you know the chore. You build a frame sequence where real keyframes are punctuated by gray filler frames, then a matching mask sequence saying "preserve these, generate those." Do it by hand and it's a spreadsheet nightmare. The Wan Vace Keyframe Builder turns that whole job into one node with a visual UI: drop images in, position them on a frame timeline, and it emits the images and the synchronized masks.
This node got real community traction when it launched - the author's r/comfyui thread drew a score of ~59 with 21 comments, and the funniest comment was the honest one: Master Kijai already has a node for this, but you need one of his per separate frame, whereas this handles the whole sequence in one place. That's the pitch, and it's a good one.
How it works
You set frame_count (2–256) and the node builds a timeline. For each keyframe image you connect (image_1, image_2, … - dynamic, so the next input appears as you use the last) you give it a position (image_1_frame, 1 = first frame). Everything else is filler. The output is two batches that line up frame-for-frame: images with your keyframes at their positions and gray (0.5 - the VACE default) or green elsewhere, and masks where keyframes are 0 (preserve) and fillers are 1 (generate).
There's real control beyond the basics. auto_spacing distributes keyframes evenly for you, with spacing_type choosing the curve (linear, ease_in, ease_out, ease_in_out) and min_spacing enforcing a floor - the tooltip's warning is worth repeating: VACE typically needs 8+ frames between keyframes for good interpolation, and this node will respect that floor. background_images lets you swap the solid filler for an actual video or control sequence, wrapping if it's shorter than frame_count - which is how you'd drive the fill from pose data instead of flat gray.
Wiring it up
The keyframes and masks feed the VACE encoder - images → input_frames, masks → input_masks - and then on to the sampler. The one community failure mode on record: the original example workflow shipped with those two connections not wired, and people understandably got nothing but junk generations until the author pushed a fix. If your first run produces garbage, check those two sockets before anything else.
Troubleshooting
- Bad generations with keyframes connected → almost always the VACE encoder inputs not wired, per above.
- Keyframe drift → your gap is too tight; respect the 8-frame floor.
- Wan 2.1 vs 2.2 - the author confirmed it's used with 2.1; 2.2 VACE is expected to behave the same but is untested by the author, so test before you trust.
- Position off by one - positions are 1-indexed (1 = first frame), which trips people who think in zero-indexed batch coordinates.
Installing
Part of TrentNodes, under Trent/Keyframes. ComfyUI Manager → "Trent Nodes" → Install, or clone it:
cd ComfyUI/custom_nodes
git clone https://github.com/TrentHunter82/TrentNodes
cd TrentNodes
pip install -r requirements.txt
Restart after. If Manager flags the pack (a day-one repo rename left a registry duplicate it still distrusts), the manual clone is the reliable path.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| frame_count | INT | 162–256 | Total number of frames in the output sequence |
| default_widthopt | INT | 83264–4096 | Width for filler frames (used if no images connected) |
| default_heightopt | INT | 48064–4096 | Height for filler frames (used if no images connected) |
| background_imagesopt | IMAGE | Optional batch of images to use instead of the filler color (e.g. a video or control sequence). Wraps if shorter than frame_count. | |
| auto_spacingopt | BOOLEAN | false | Automatically distribute keyframes evenly across the frame range |
| spacing_typeopt | COMBO | linear | Spacing curve type: linear (even), ease_in (slow start), ease_out (slow end), ease_in_out (slow both ends) |
| min_spacingopt | INT | 81–64 | Minimum frames between keyframes (VACE typically needs 8+ for good interpolation) |
| image_1opt | IMAGE | — | |
| image_1_frameopt | INT | 11–256 | Frame position for this image (1 = first frame) |
| filler_coloropt | COMBO | gray | Color for filler frames: gray (0.5, Wan VACE default) or pure green (chroma-key style) |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | Batch of frames: keyframes at specified positions, background or solid filler elsewhere |
| masks | MASK | Batch of masks: 0 for keyframes (preserve), 1 for filler frames (generate) |