Skip to main content

Find the longest seamlessly-loopable segment in a video via normalized cross-correlation.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loopsmith-0.1.0.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loopsmith-0.1.0-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file loopsmith-0.1.0.tar.gz.

File metadata

  • Download URL: loopsmith-0.1.0.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for loopsmith-0.1.0.tar.gz
Algorithm Hash digest
SHA256 045ac2f6d6d8b2fd6b39fc1de07ec6d67a0131a75bb8d2395b9c83ad08831b61
MD5 839b2447fc79c66267773ae43cf6d476
BLAKE2b-256 e12bc09b4e9150b3e3a72c44747546ee374d73e6a526d29c2da61c77a6628ef8

See more details on using hashes here.

Provenance

The following attestation bundles were made for loopsmith-0.1.0.tar.gz:

Publisher: publish.yml on jpratt9/loopsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loopsmith-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: loopsmith-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for loopsmith-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87c906aec9f72b5bcb3c7f3a0996e6e3a87943931f46fb35a27e066a7809ae54
MD5 c89c882ae2fbbef2d4b46cf07377bbd2
BLAKE2b-256 9cd1736d3751f1b49ecc0e6fe7c9acbab187b000ca447680e552de7dc4f92c7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for loopsmith-0.1.0-py3-none-any.whl:

Publisher: publish.yml on jpratt9/loopsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page