Nodes/VACE Automation/VACE Join Assemble
ComfyUI Node

VACE Join Assemble

Stitch the seam back together — loop pass included

By EnviralDesign·Created 6 months ago·Updated 3 months ago· 0
VACE Join Assemble
  • start_images
  • transition_images
  • end_images
  • images
is_final_loop_pass
context_frames
replace_frames
debugfalse

VACE Join Prep builds the seam's control window; your VACE nodes generate the transition; VACE Join Assemble is where it all comes back together. It takes the three pieces - the kept start of clip A, the generated transition, and the kept start of clip B - and concatenates them into one continuous clip. And it has one extra trick: when is_final_loop_pass is on, it switches to the tail-to-head logic so the same node can also close a loop without a second, separate assembly path.

How it works

Normally it's a straightforward stitch:

output = start_images + transition_images + end_images

start_images is the body of clip A (with the replaced tail trimmed), transition_images is the crossfaded VACE output, end_images is clip B's body (with the replaced head trimmed). The node validates that all three match resolution before concatenating.

On the final loop pass, the behavior changes:

  • It drops the trailing context_frames of guidance from the transition (transition = transition[:-context_frames]) - those frames were just context anchoring the generation, not meant to be visible.
  • It does not append end_images. On the loop pass, the "second clip" is really the first clip again, and appending its body would duplicate footage. So the output is just start_images + trimmed transition, and the loop closes into the first clip's body instead of repeating it.

The README phrases it as assembling "without duplicating or extending the first clip body," and that's the bit to remember: the final loop pass reuses the retained body rather than copying the whole clip a second time.

Inputs and outputs that matter

  • start_images, transition_images, end_images (IMAGE) - the three seam pieces
  • is_final_loop_pass (BOOLEAN, forced input) - wire it from VACE Clip Loop Start's output of the same name, so it's true only on the last pass
  • context_frames and replace_frames (INT, forced inputs) - echoed through from prep so the node knows how many guidance frames to trim on the loop pass
  • debug (boolean, default false) - prints frame counts, including how many transition frames were emitted after trimming

Output is a single images batch - the joined clip, ready for VAE decode.

Installing it

Part of the comfy-vace-automation pack, no extra pip dependencies:

cd ComfyUI/custom_nodes
git clone https://github.com/EnviralDesign/comfy-vace-automation

Restart ComfyUI, or install via ComfyUI Manager (search "comfy-vace-automation").

When it bites you

  • Forced inputs. is_final_loop_pass, context_frames, and replace_frames are all forced-input, so they must be wired (usually from Loop Start and Join Prep), not typed. Missing links mean the node won't execute.
  • Resolution mismatch. All three pieces must match - this is the node that will tell you if your VACE decode came back at a different size than the source clips. Re-run with matching dimensions.
  • Loop pass with a too-short transition. If the transition is shorter than context_frames, the trim on the final pass errors out. Generate enough frames on the VACE side before assembling.

One way to think of the two-node split: Join Prep is the question ("what do I want the model to regenerate?"), Join Assemble is the answer ("here's the finished seam, in the right order"). Keep them wired as a matched pair and the loop logic just works.

Categoryvideo/VACE

Inputs (7)

NameTypeDefaultDescription
start_imagesIMAGE
transition_imagesIMAGE
end_imagesIMAGE
is_final_loop_passBOOLEAN
context_framesINT
replace_framesINT
debugBOOLEANfalse

Outputs (1)

NameTypeDescription
imagesIMAGE