Nodes/KJNodes for ComfyUI/Close Tensor Loop
ComfyUI Node Runs on cloud

Close Tensor Loop

Where looped video actually comes together

By kijai·Created 3 years ago·Updated 2 days ago· 3,208
Close Tensor Loop
  • flow_control
  • processed
  • output
accumulatetrue
overlap
stopfalse

TensorLoopClose is the other half of kijai's experimental native loop, and it's the half that does all the clever work. TensorLoopOpen hands you previous_value and loop control; you generate one iteration's worth of output; TensorLoopClose takes that output, stashes it, trims the seam, and decides whether to run the body again. When the loop finally ends, it hands back one clean batch. If you're making long video by chaining short generations - the "last frame feeds the next chunk" trick that people have been hand-rolling since Wan and LTX arrived - this node is what that hack looks like when someone bothers to build it properly.

What it actually does

It closes the loop and accumulates. Connect flow_control from TensorLoopOpen, feed the current iteration's result into processed, and it appends to a running accumulation. When the loop is done it concatenates everything into a single IMAGE, MASK, or LATENT batch - including video latents, where it correctly concatenates along the temporal dimension.

Under the hood this is ComfyUI's graph-expansion API doing the heavy lifting. TensorLoopClose expands into a subgraph at execution time: it unpacks the loop state, decrements the iteration counter, appends your processed output to the accumulation, then hands control to a while-loop primitive that re-runs the body with fresh values. If you open a workflow that uses this pack you'll see a swarm of _-prefixed helper nodes appear (Accumulate, Batch Ops, Image Accum State Pack…) - those are this node's internals, and they're hidden from the node menu on purpose.

The inputs that matter

  • flow_control - from TensorLoopOpen. Required.
  • processed - "Output generated this iteration." Whatever your loop body produced. Required.
  • accumulate (default on) - when on, collects every iteration into a batch; when off, only the final iteration's result comes out the other end. Turn it off when you only care about the last chunk.
  • overlap - how to handle the context frames a video model re-generates. This is the input that makes long-video work actually usable:
    • disabled - keep every frame as-is (you'll see duplicated context frames at each seam).
    • start - cut overlap_frames from the start of each iteration after the first. Right for models that regenerate their context at the start of their output, which is the common case for video continuation.
    • end - cut from the end of each iteration, and re-append the trimmed tail of the final generation.
    • fade_linear / fade_smooth - crossfade the end of each iteration into the start of the next with a linear or smoothstep ramp, instead of cutting. Smoother seams, at the cost of blending rather than hard-cutting.
  • stop (optional, default false) - an early-stop signal from inside the loop body. Wire a boolean node into it and the loop ends after the current iteration, ignoring whatever's left in the count or frame target. Great for "generate until I like it, then cut."

The output

A single output - the accumulated batch if accumulate is on, or just the final iteration's result if it's off. Feed it straight into a VAE decode or a video encoder.

Install and gotchas

Same as the rest of the pack:

cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-NativeLooping_testing

Restart ComfyUI, or search "NativeLooping" in Manager. No models to download. The real dependency is a current ComfyUI - the pack relies on the newer extension API (comfy_api.latest) and comfy.nested_tensor, so an old build won't even load it.

A few traps worth knowing. This is a _testing repo from kijai - the author's own README says it's temporary, a candidate for native loop nodes in core ComfyUI, so treat the API as moving. Don't combine accumulate off with total_frames mode on the open node; frame counting is disabled when you're not accumulating so the loop can't run forever. And when iterations is 0 on the open node, the whole loop is bypassed and this node just passes initial_value through - handy, but it means the Close node's job quietly disappears, which confuses people the first time.

Categoryadvanced/looping

Inputs (5)

NameTypeDefaultDescription
flow_controlFLOW_CONTROL
processedCOMFY_MATCHTYPE_V3Output generated this iteration.
accumulateBOOLEANtrueWhen enabled, collects all iterations into a batch. When disabled, only outputs the final iteration's result.
overlapCOMBOHow to handle duplicate frames where consecutive iterations overlap (e.g. context frames a video model re-generates). - disabled: keep every frame as-is - start/end: cut the duplicates from the start or end of each iteration's output - fade_linear/fade_smooth: crossfade the end of each iteration into the start of the next
stopoptBOOLEANfalseOptional early stop signal from inside the loop body. When True, the loop stops after the current iteration regardless of remaining iterations or total_frames target.

Outputs (1)

NameTypeDescription
outputCOMFY_MATCHTYPE_V3Accumulated batch or final iteration result, depending on 'accumulate' setting.