Skip to main content

loopsmith

Find the longest seamlessly-loopable segment in a video.

Given a clip, loopsmith figures out the longest stretch you can pull out and play on repeat without a visible jump — the point where some later frame looks almost exactly like an earlier one, so playback can snap back to the start with no seam. Handy for turning B-roll, animations, or background footage into clean loops (looping wallpapers, GIFs, video backdrops, and so on).

How it works

The core of it is a single matrix multiply.

  1. Sample every Nth frame, shrink each to a 160px thumbnail, convert to grayscale, and z-score normalize it (subtract the mean, divide by the standard deviation).
  2. Stack the normalized frames into a matrix and multiply it by its own transpose. For z-scored vectors, each dot product (divided by the pixel count) is the normalized cross-correlation between two frames — a similarity score from -1 to 1 where 1 means "visually identical." So one mat @ mat.T produces the score for every pair of frames at once.
  3. For each pair of frames, the gap between them is a candidate loop length. Among all pairs whose similarity clears a threshold, the one with the largest gap wins: those two near-identical frames are the in- and out-points of the longest seam-free loop.

Because the expensive step is one BLAS matmul, it stays quick even though it's effectively comparing every frame against every other frame.

Install

pip install loopsmith

From source, for development (includes the test deps):

pip install -e ".[dev]"

Needs Python 3.9+, OpenCV, and NumPy — the last two are pulled in automatically.

Usage (CLI)

# Analyze a single video
loopsmith clip.mp4

# Batch every .mp4/.mov in a directory
loopsmith ./footage/

# Loosen or tighten the similarity threshold (default 0.85)
loopsmith clip.mp4 --threshold 0.80

# Sample every 5th frame instead of every 3rd (faster, coarser)
loopsmith clip.mp4 --downsample 5

# Detailed report: top 10 loops by similarity and by length
loopsmith clip.mp4 --detail

# Find the best loop closest to a target length, in seconds
loopsmith clip.mp4 --detail --target-length 6

Batch mode prints the best loop per file as a table; --detail (single file) prints the top candidates plus a yes/no "is this clip loopable" verdict.

Usage (library)

from loopsmith import extract_frames, find_best_loop

rows, frame_indices, fps, total = extract_frames("clip.mp4", downsample=3)
loop = find_best_loop(rows, frame_indices, threshold=0.85)
if loop:
    start_frame, end_frame, ncc = loop
    seconds = (end_frame - start_frame) / fps
    print(f"Loop {start_frame}->{end_frame} ({seconds:.1f}s) at {ncc:.1%} similarity")

Other helpers: find_best_for_target() (the loop closest to a target duration), find_top_loops() (ranked candidates), and analyze_video() (a one-call summary dict).

Notes & limitations

  • Visual only. It compares frames, not audio. A visually seamless loop can still have an audible seam — check the sound separately if that matters.
  • Cut resolution. In/out points are accurate to within --downsample frames, since that's the sampling step. Lower it for tighter cuts at the cost of speed.
  • Scales as O(N²) in sampled frames. It builds an N×N similarity matrix, so for long videos raise --downsample to keep time and memory in check.
  • It reports, it doesn't cut. Output is frame indices / timestamps and similarity scores; trimming the actual clip (e.g. with ffmpeg) is up to you.

License

MIT — see LICENSE.

Metadata

Release files for loopsmith 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for loopsmith 0.1.0
File Size Uploaded
loopsmith-0.1.0.tar.gz 8.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for loopsmith 0.1.0
File Interpreter ABI Platform
loopsmith-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 16.3 kB

Release files / loopsmith-0.1.0.tar.gz

Download URL loopsmith-0.1.0.tar.gz
Size 8.8 kB
Tags Source
SHA-256 checksum
How to use checksums
045ac2f6d6d8b2fd6b39fc1de07ec6d67a0131a75bb8d2395b9c83ad08831b61
BLAKE2b-256 checksum
How to use checksums
e12bc09b4e9150b3e3a72c44747546ee374d73e6a526d29c2da61c77a6628ef8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 23, 2026.

Transparency log

Release files / loopsmith-0.1.0-py3-none-any.whl

Download URL loopsmith-0.1.0-py3-none-any.whl
Size 7.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
87c906aec9f72b5bcb3c7f3a0996e6e3a87943931f46fb35a27e066a7809ae54
BLAKE2b-256 checksum
How to use checksums
9cd1736d3751f1b49ecc0e6fe7c9acbab187b000ca447680e552de7dc4f92c7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page