๐ Autocrop to Loop
The best loop is the one you already have โ this node finds where it starts
- clip_frames
- cropped_clip
- end_crop_frames
- cropped_length
- score
- diagnostics_csv
Here's the trick the pros use that beginners don't: you don't always need to generate a perfect loop. A lot of the time the loop is already in your footage - you just need to find the right end point. Autocrop to Loop is the node that hunts for it. It takes your clip, tests every possible end-crop from 0 up to max_end_crop_frames, scores how well each candidate's seam would match the clip's normal motion, and hands you the crop that loops best. The output is a shorter, loopier clip - plus the diagnostics so you can see why it chose that cut.
The author's line for this one is "the best loop is the one you already have," and it's the correct instinct. A generated seam is expensive and can fight the source footage; a well-chosen cut is free and looks native because it is native. Run this before the interpolate-the-seam workflow and you're feeding the interpolator the best possible starting point.
How it works
For every crop size from 0 to max_end_crop_frames, the node aligns the cropped clip's end against its beginning and scores the resulting seam on a weighted blend of metrics:
- Step-size match (
weight_step_size, default 0.55) - how well the lastโfirst jump matches the amount of motion between normal neighboring frames. This is the anti-freeze/anti-jump guard. - Visual similarity (
weight_similarity, default 0.3, uses SSIM at scales fromssim_downsample_scales) - the seam should look like an ordinary neighbor pair, not a cut. - Exposure continuity (
weight_exposure, default 0.1) - smooth brightness across the seam, so you don't get a flicker pop. - Motion continuity (
weight_flow, default 0.05) - consistent optical flow across the seam. Note this one needs OpenCV and is off by default (use_flow_guard), because it's the slowest and the only one with an extra dependency.
include_first_step and include_last_step pick which neighbor pairs inside the clip define "normal" motion; seam_window_frames averages over multiple aligned pairs for robustness.
The inputs that matter
- clip_frames - your footage.
- max_end_crop_frames - the search budget. Higher = more candidates (slower) but potentially a better loop. 12 is a sensible default; crank it if you're hunting for a gem in a long clip.
- include_first_step / include_last_step / include_global_median_step - what counts as normal motion. Median helps when your footage has outlier frames.
- accelerate_with_gpu and use_mixed_precision - both default on; the scoring runs on CUDA for a big speedup with identical results.
The outputs
- cropped_clip - your loop-ready footage.
- end_crop_frames - how many frames were cut off the end.
- cropped_length - the new length.
- score - how good the chosen seam was.
- diagnostics_csv - per-candidate scores, for the person who wants to know why.
Installing it
Part of the WhiteRabbit pack, installed once:
cd ComfyUI/custom_nodes
git clone https://github.com/Artificial-Sweetener/comfyui-WhiteRabbit
cd comfyui-WhiteRabbit
python -m pip install -r requirements.txt
or ComfyUI Manager โ "WhiteRabbit". The pack targets ComfyUI's v3 node API - keep ComfyUI current. The only pip dependency is torchlanc.
Where people get burned
- Enabling
use_flow_guardwithout OpenCV. It'll error out if OpenCV isn't in your environment. Leave it off unless you specifically want motion-continuity scoring. - Over-allocating the weights. The four weights are relative, not absolute - start from the defaults and nudge one at a time. A "1,1,1,1" flat spread usually underperforms the defaults.
- Expecting magic from a static shot. If the clip has no motion to match, every crop scores about the same. That's footage problem, not a node problem.
Feed the cropped_clip into Prepare Loop Frames and let the seam workflow take it from there. This is the node I'd run first on any clip I was trying to loop.
Inputs (18)
| Name | Type | Default | Description |
|---|---|---|---|
| clip_frames | IMAGE | Your full clip (NHWC, 0โ1). Tries every crop from 0..max_end_crop_frames and returns the best loop. | |
| max_end_crop_frames | INT | 120โ10000 | Largest crop to test at the END. Higher = more candidates (slower), but potentially better. |
| include_first_step | BOOLEAN | true | Use the first neighbor pair (frame 0โ1) as a target step size/similarity. |
| include_last_step | BOOLEAN | true | Use the last neighbor pair inside the KEPT region as a target. |
| include_global_median_step | BOOLEAN | false | Also use the median step across the KEPT region (needs โฅ3 frames). Helps ignore outliers. |
| seam_window_frames | INT | 21โ6 | Average over multiple aligned pairs across the seam. Larger = more robust. |
| distance_metric | COMBO | L1 | How to measure step size for matching. L1 is usually more forgiving; MSE penalizes big errors more. |
| score_in_8bit | BOOLEAN | false | Score with an 8-bit view (simulate export). Output video still stays float. |
| use_ssim_similarity | BOOLEAN | true | Include SSIM so the seam โlooksโ like a normal neighborโavoid freeze or jump. |
| use_exposure_guard | BOOLEAN | true | Promote smooth brightness across the seam (reduces flicker pops). |
| use_flow_guard | BOOLEAN | false | Encourage consistent motion across the seam (needs OpenCV; slower). |
| weight_step_size | FLOAT | 0.550โ1 | Importance of matching step size. Higher = less freeze/jump risk. |
| weight_similarity | FLOAT | 0.300โ1 | Importance of visual similarity (SSIM). Helps avoid a frozen-looking seam. |
| weight_exposure | FLOAT | 0.100โ1 | Importance of even brightness across the seam. |
| weight_flow | FLOAT | 0.050โ1 | Importance of motion continuity across the seam. |
| ssim_downsample_scales | STRING | 1,2 | SSIM scales to average, as a comma list. Example: 1,2 = full-res and half-res. |
| accelerate_with_gpu | BOOLEAN | true | If ON and CUDA is available, run scoring on GPU for a big speedup (same results). |
| use_mixed_precision | BOOLEAN | true | If ON (with GPU), use mixed precision for SSIM/conv math (faster on larger clips). |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| cropped_clip | IMAGE | โ |
| end_crop_frames | INT | โ |
| cropped_length | INT | โ |
| score | FLOAT | โ |
| diagnostics_csv | STRING | โ |