Nodes/was-node-suite-comfyui/Video Seamless Loop
ComfyUI Node Runs on cloud

Video Seamless Loop

Find the loop hiding in your clip

By WASasquatch·Created 4 years ago·Updated a day ago· 1,864
Video Seamless Loop
  • video
  • video
  • start
  • length
  • join_difference
  • report
◄min_seconds2.0►
◄max_seconds0.0►
◄blend_frames8►
◄max_difference0.0►
◄blend_modeauto►

Looping used to be AnimateDiff's one unassailable feature - the community held onto it long after everything else Wan-side overtook the pack, and the threads asking how to get a ping-pong-free loop out of Wan 2.2 are the evidence. Looping hasn't stopped being awkward. What changed is that you can now retrofit one.

Video Seamless Loop takes a clip, looks for the stretch whose end runs back into its start most closely - picture and movement - cuts that out, and blends the join along the motion so it plays as a loop. This is the node for a background plate, an idle animation, a four-second menu loop, or a product turntable that never quite closed.

Inputs

video is the clip. min_seconds (default 2) and max_seconds (default 0, meaning "up to the whole clip") define the search window. Set max_seconds to 4 and you will always get a loop under four seconds if one exists in there.

blend_frames is how many frames are blended across the join: 0 cuts straight back and shows the seam, 8 is the default, 24 gives a long, soft return. More blending hides a worse match at the cost of a soft mush around the join - a shot with a fast-moving subject will ghost there.

max_difference is the quality gate and the most useful setting on the node. It is how far apart, in levels of 255, the two ends may be: 0 takes the closest match no matter how bad, 3 is clean, 6 is slight. Above 0 the node takes the longest loop within that tolerance and stops if none qualifies - which means you get told when your clip simply does not contain a loop instead of a silent bad one. Use 3 for anything you are going to publish.

blend_mode is auto by default: it uses motion, which carries frames into each other along their movement, when the ends are under 8 levels apart, and falls back to crossfade - a straight dissolve, which ghosts rather than tears - above that. You can force either.

Outputs

video is the loop, joined. start is the source frame the loop starts on, counting from 0, and length is the loop's frame count - between them you have everything you need to describe the loop to another node, or to trim the original in a separate pass. join_difference is the mean difference between the two ends before blending, in levels of 255: under 3 is clean, over 8 shows. report says the same thing in words.

Trust join_difference more than your eyes on the first watch. The whole reason a loop gets missed is that a bad join looks fine for one cycle and obvious on the tenth.

Install

ComfyUI Manager → search WAS Node Suite v3 → install → restart. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git

ComfyUI 0.14.0+ and Python 3.10+. The pack installs no packages - requirements.txt is a single comment, pip never runs, and nothing is fetched over the network while features.network is off in config.yaml. No model weights needed for this node; the motion comparison uses the pack's own flow code, and a learned flow network in ComfyUI/models/optical_flow is optional. First start, and the first start after an update, takes an extra second or two.

Where it goes wrong

The clip has no loop in it. A shot that moves relentlessly forward - someone walking, a camera dolly - has no stretch whose end resembles its start, and no amount of blending fixes that. The node will tell you via join_difference. The fix is upstream: generate a clip whose motion returns, use a ping-pong edit, or accept a longer loop.

Long clips, long search. The window search compares many candidate starts, so a two-minute clip with min_seconds at 2 is a lot of comparisons. Constrain max_seconds.

Blend frames as a repair tool. If blend_frames needs to be 24 to hide the join, the join is wrong and you are smearing a second of footage to bury it. Raise max_difference and let the node find a better cut point instead.

Audio. The loop carries audio, and a loop join in sound is much more audible than one in picture - a click at the seam is nearly unavoidable. If the loop is going to play with music over it, drop the clip's audio and let the music loop.

CategoryWAS Suite/Animation

Inputs (6)

NameTypeDefaultDescription
videoVIDEOThe clip to loop.
min_secondsFLOAT2.00.1–600Shortest loop in seconds: 1 = a quick cycle; 2 = default; 5 = a long take.
max_secondsFLOAT0.00–600Longest loop in seconds: 0 = up to the whole clip; 4 = keeps it under four seconds.
blend_framesINT80–240Frames blended across the join: 0 = cut straight back; 8 = default; 24 = a long, soft return.
max_differenceFLOAT0.00–255Most the two ends may differ, in levels of 255: 0 = take the closest match; 3 = clean; 6 = slight. Above 0, the longest loop within it is taken, and the run stops if none is.
blend_modeCOMBOauto'auto' = 'motion' for ends under 8 levels apart, 'crossfade' above; 'motion' carries the frames into each other along their movement where it can be followed; 'crossfade' dissolves, ghosting rather than tearing.

Outputs (5)

NameTypeDescription
videoVIDEOThe loop, its join blended, with its audio.
startINTThe source frame the loop starts on, counting from 0.
lengthINTFrames in the loop.
join_differenceFLOATMean difference between the two ends before blending, in levels of 255: under 3 is clean, over 8 shows.
reportSTRINGThe loop and how clean its join is, in words.