Seamless Loop Splitter
Cut a video into a seamless-loop skeleton — the last-frame-meets-first trick, minus the mental math
- images
- vfi_batch (Last & First)
- head_chunk
- tail_chunk
A video that loops seamlessly is just a video whose last frame flows into its first. That's the whole trick, and it's been the community's loop recipe forever: take the clip's last and first frames, synthesize the transition between them, then splice it back in. This node is the cut half of that recipe. Give it an image sequence and it hands you three pieces: the two chunks of original footage, plus a tidy 2-frame batch of [last, first] ready for any frame-interpolation (VFI) node to bridge.
The assembly half is its sibling, SeamlessLoopAssembler, in the same pack. Together they're the cheap, no-model alternative to the VACE Video Joiner "Make Loop" approach - no Wan VACE model, no re-generation, just deterministic interpolation. The trade-off is real and worth internalizing: interpolation produces a morph, not newly generated motion. If you need the smoke to keep rising through the seam, VACE wins. If you need a clip that cycles without a visible jump cut, this is faster and doesn't eat VRAM. That's the honest version of the trade - AnimateDiff had native looping that people still miss, and this is the DIY version for Wan-era clips.
How it works
Straight from the source, it's three cuts. split_idx is total_frames × offset_ratio, clamped so each chunk keeps at least one frame. Then:
- vfi_batch =
[last frame, first frame]- the pair you feed to a VFI node. - head_chunk = frames from the split point up to (not including) the last frame.
- tail_chunk = frames from just after the first frame up to (not including) the split point.
Here's the part that trips everyone: the naming is relative to the rebuilt loop, not your source video. head_chunk isn't the start of your clip - it's the frames after the cut point. tail_chunk is the frames before it. Read them as "what sits either side of the interpolated seam," and the wiring clicks.
The inputs that matter
- images - your image sequence (the frame tensor out of a video sampler or VAE decode).
- offset_ratio - where the cut lands, as a fraction of total frames. Default
0.5splits roughly in half; range0.1–0.9, stepped by0.1. It's a ratio, not a frame number - want 24 frames in one chunk of an 81-frame clip? Set0.3, don't type 24.
Outputs
- vfi_batch (Last & First) - a 2-frame batch of the last and first frames. This is the interpolation pair; wire it into your VFI node.
- head_chunk and tail_chunk - the original footage, held for the assembler.
The pipeline reads: vfi_batch → your VFI node → the interpolated result and both chunks → SeamlessLoopAssembler, in order.
Install
ComfyUI Manager, search ComfyUI-AtlasUtils, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Yoon999/ComfyUI-AtlasUtils
Restart ComfyUI. No model downloads, no pip deps - this pack ships zero interpolation; you bring the VFI node (the RIFE-class interpolation packs are the usual picks).
Where people get burned
- Fewer than 3 frames in - it returns everything unchanged and logs a console warning. There's nothing to split.
- "My chunks look wrong" - revisit the naming above. head/tail are about the loop, not the source.
offset_ratiois not a frame index. Every other video tool takes a number; this takes a fraction. It's the one real footgun.- No VFI here - if you wire
vfi_batchstraight into the assembler you're just stacking 2 frames into the middle of your loop. You need an interpolation node between them.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| offset_ratio | FLOAT | 0.50.1–0.9 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| vfi_batch (Last & First) | IMAGE | — |
| head_chunk | IMAGE | — |
| tail_chunk | IMAGE | — |