Seamless Loop
Seamless Loop Finds the Seam Your Clip Already Had — Then Morphs It Shut
- images
- images
Every video model since AnimateDiff has the same hole: it can't loop. AnimateDiff looped natively; Wan and LTX don't. So people either ping-pong the clip - plays backwards, reads as a bounce - or regenerate the join with VACE, which morphs, which is why the argument goes "if you can see the transition, it's the very seam you're referring to." Seamless Loop takes a third road: nothing is regenerated. It finds where your clip's tail best matches its head, and interpolates the two into each other.
One node, one in, one out - and the most useful thing in this pack if you're assembling loops from footage you can't re-roll.
How it works
Analysis first. Every frame gets squashed to a ~48px preview (area-averaged, near-free), then it brute-forces a grid: start and end trims of 0, half, or all of a 10% maximum, crossed with overlap lengths from 8/12/18/25% of the remaining clip, clamped to 3–64 frames. Each candidate gets a cost from exposure-compensated MSE, local SSIM, gradient difference, a temporal-motion term, plus small penalties for shortening the clip and for scene-cut spikes. Cheapest wins. Small uniform exposure differences are correctable; geometry isn't.
Then the morph. The chosen tail frames are interpolated against the head frames with a real RIFE or FILM checkpoint, run bidirectionally (forward and backward, averaged) to cut direction-dependent artifacts. Timing is eased with a smoothstep, and there's a bounded exposure match - clamped to ±0.04 per channel, fading to zero at both joins - so you don't get a colour pop. Your middle frames copy through untouched, and the playback wrap lands inside the original footage rather than on an interpolator's endpoint.
Special cases are handled properly. Static batches pass through untouched. Already-closed clips skip interpolation entirely and, with exact_endpoint off, drop the duplicate end frame. Clips under six frames have no context to analyse, so it bridges the endpoints with max(3, len(images)) interpolated frames. Every run logs N → M frames; trim=…, overlap=…, analysis PSNR=… dB, temporal spike=…x, and warns when the spike ratio passes 12 - your cue that the loop is going to look bad.
Inputs and outputs
images(required) - a decoded RGB batch,[frames, height, width, 3], straight from a video loader or your sampler's decoded output. RGBA raises aValueError.model_name- the interpolation checkpoint. The dropdown lists the.safetensorsfiles inmodels/frame_interpolation/(convertible to an input socket). RIFE 4.26 is what the author inference-tested; FILM uses the same native loader but was never verified with a local checkpoint.exact_endpoint(off by default) - copies the first output frame to the end. That makes first and last tensors identical and adds one duplicated frame per cycle, which you will see as a hitch. The tooltip says leave it off for continuous playback. Trust that. It's a widget-only flag, so you can't wire it to a switch.- Output: one
imagesbatch - into Enhanced Video Combine,VHS_VideoCombine, or any saver.
Install
ComfyUI Manager → search DaSiWa-Nodes. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/darksidewalker/ComfyUI-DaSiWa-Nodes
cd ComfyUI-DaSiWa-Nodes
pip install -r requirements.txt
# restart ComfyUI
Two things to know before you run that pip line. First, it installs the whole pack's dependencies: nvidia-vfx (the reason the README demands an RTX GPU and driver 530+), av>=18, transformers, llama-cpp-python, psutil. Seamless Loop itself needs none of it - it's pure PyTorch calling ComfyUI's native frame interpolation loader. On AMD, an old driver, or a slim container, those extras are where your install breaks - and since nodes share one environment, a hard pin here can change what another pack gets. Second: nothing in requirements.txt gets you a model. Download a ComfyUI-compatible RIFE .safetensors (RIFE 4.26 is the safe pick) and drop it in:
ComfyUI/models/frame_interpolation/
Restart, and model_name will have something in it.
Common issues
Empty model_name dropdown, or "Select a native RIFE/FILM .safetensors model from models/frame_interpolation." No checkpoint in the folder. The node refuses anything that isn't .safetensors, and checks the file exists before loading.
You can still see the join. The node's own description says arbitrary footage can't be guaranteed artifact-free, and the log warning fires when strong motion or a scene discontinuity survives. Cuts, occlusion, camera travel - no overlap search fixes geometry it can't find. Re-generate, or take a slice where head and tail actually resemble each other.
Your audio drifts out of sync. Frame count and starting frame can both change. Align audio after the loop node; feeding the original audio in at the original offset is how people end up with a drift they blame on the encoder.
Analysis PSNR looks great but the loop still stutters. That number is measured on 48px previews. It says the join matched, not that the motion reads as continuous.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| model_nameopt | COMBO | RIFE / FILM only: native safetensors in models/frame_interpolation. Ignored for RTX Frame Generation. | |
| exact_endpointopt | BOOLEAN | false | Copy the first frame to the end: exact pixels, but one duplicate frame on repeat. Disable for continuous playback. |
| interpolation_backendopt | COMBO | RIFE / FILM | RIFE / FILM: native checkpoint interpolation (default). RTX Frame Generation: NVIDIA VFX pair interpolation without a RIFE/FILM checkpoint; requires a supported NVIDIA GPU and SDK. Both morph only the loop transition, not the whole video's frame rate. |
| rtx_modeopt | COMBO | HIGH | RTX only: LOW favors speed, MEDIUM is the middle tier, HIGH favors quality. Ignored for RIFE / FILM. |
| rtx_device_idopt | INT | 00–8 | RTX only: CUDA device index, 0 is the first GPU. Ignored for RIFE / FILM. Output still follows ComfyUI's intermediate-device policy. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |