Skip to main content

Extract frames from a video and compose them into a single mosaic image.

Project description

video-mosaic

Extract frames from a video and arrange them into a single mosaic image.

Python 3.10+ License: MIT PyPI

What it does

video-mosaic takes a video file (or URL), extracts frames, and composes them into a grid — like a contact sheet or storyboard. It includes a header with video metadata and optional timestamps on each frame. Supports YouTube, Twitter/X, TikTok, Instagram, and any site supported by yt-dlp.

┌─────────────────────────────────────────┐
│  filename.mp4                           │
│  1920×1080  •  30.2s  •  30.00 fps      │
├──────┬──────┬──────┬──────┬──────┬──────┤
│  #1  │  #2  │  #3  │  #4  │  #5  │  #6  │
│00:00 │00:05 │00:10 │00:15 │00:20 │00:25 │
├──────┼──────┼──────┼──────┼──────┼──────┤
│  #7  │  #8  │  #9  │ #10  │ #11  │ #12  │
│00:30 │00:35 │00:40 │00:45 │00:50 │00:55 │
└──────┴──────┴──────┴──────┴──────┴──────┘

Installation

With pip

pip install video-mosaic

With Homebrew (macOS / Linux)

brew tap GonzaloFuentes28/tap
brew install video-mosaic

From source

git clone https://github.com/GonzaloFuentes28/video-mosaic.git
cd video-mosaic
pip install .

Prerequisites

ffmpeg must be installed and available in your $PATH.

# macOS
brew install ffmpeg

# Ubuntu / Debian
sudo apt install ffmpeg

# Arch
sudo pacman -S ffmpeg

Quick start

# 48 evenly-spaced frames with timestamps
video-mosaic video.mp4 --frames 48 --labels

# One frame every 5 seconds
video-mosaic video.mp4 --every 5s -o contact-sheet.jpg

# Every single frame of a short clip
video-mosaic clip.mp4 --all -o all-frames.png

# From a URL (requires yt-dlp)
video-mosaic "https://youtube.com/watch?v=abc" --frames 48 --quality 720
video-mosaic "https://x.com/user/status/123" --frames 24

Usage

video-mosaic INPUT [options]

Frame selection (pick one)

Flag Description
--frames N Extract exactly N frames, evenly distributed
--every INTERVAL One frame per interval (5s, 500ms, 0.5)
--all Every single frame (careful with long videos)

Trimming

Flag Description
--from TIME Start time (1:30, 90, 0:05.5)
--to TIME End time (2:30, 150)
# Frames only from the first minute
video-mosaic video.mp4 --frames 24 --from 0:00 --to 1:00

Filtering

Flag Description
--skip-black Exclude mostly-black frames
--skip-dupes Exclude near-duplicate consecutive frames
# Clean up a screencast with lots of static frames
video-mosaic screencast.mp4 --every 1s --skip-dupes --skip-black

Layout

Flag Default Description
--cols N auto (√n) Number of columns
--thumb-width PX native Thumbnail width in pixels
--padding PX 2 Gap between frames
--bg COLOR #1a1a1a Background color (hex)
--labels off Show frame number + timestamp
--no-header Hide video info header
--reverse Reverse frame order
# Custom layout: 10 columns, smaller thumbnails, white background
video-mosaic video.mp4 --frames 100 --cols 10 --thumb-width 200 --bg "#ffffff"

Output

Flag Default Description
-o PATH mosaic.jpg Output image (.jpg, .png, .webp)
--pdf PATH Also export as multi-page PDF storyboard
# Image + PDF storyboard
video-mosaic video.mp4 --frames 48 --labels --pdf storyboard.pdf

URL downloads

Flag Description
--quality PX Max video height for URL downloads (e.g. 720, 1080)

Requires yt-dlp: pip install yt-dlp or brew install yt-dlp.

Other

Flag Description
--open Open the output image after saving
--no-progress Disable progress bar

Examples

# Quick overview of a movie trailer
video-mosaic trailer.mp4 -o overview.jpg --frames 36 --cols 6 --labels

# Frame-by-frame analysis of a 2-second clip
video-mosaic clip.mp4 -o analysis.png --all --labels

# Every 10 seconds of a long lecture, skip static slides
video-mosaic lecture.mp4 -o sheet.webp --every 10s --skip-dupes --thumb-width 400

# Just the intro of a video, reversed, as PDF
video-mosaic video.mp4 --frames 20 --from 0:00 --to 0:30 --reverse --pdf intro.pdf

Project structure

src/video_mosaic/
├── __init__.py   # Package root, version, VideoMosaicError
├── cli.py        # CLI argument parsing and orchestration
├── download.py   # URL video downloading via yt-dlp
├── probe.py      # Video metadata via ffprobe
├── extract.py    # Frame extraction strategies
├── filters.py    # Black frame / duplicate detection
├── mosaic.py     # Grid composition
├── pdf.py        # PDF storyboard export
└── utils.py      # Timestamp parsing, font loading

Contributing

git clone https://github.com/GonzaloFuentes28/video-mosaic.git
cd video-mosaic
pip install -e ".[dev]"

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

video_mosaic-0.1.0.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

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

video_mosaic-0.1.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for video_mosaic-0.1.0.tar.gz
Algorithm Hash digest
SHA256 58f1cfcc5cb4a67f40fadfc13d86f401aa3517bde916bb54ae52742be329d99e
MD5 cc8632781e3599903d0e69ffbb794476
BLAKE2b-256 6c916fd52d2ed4510c38aecd30cf2d641a915a7bef56932569f6f33477b2eec7

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on GonzaloFuentes28/video-mosaic

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

File details

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

File metadata

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

File hashes

Hashes for video_mosaic-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2296aa7565de9b99eabf7b28c9180a45fd367d1c1d6150479d15d47686ee53be
MD5 f2c4b33f923dfc9e2df0f11b9d198408
BLAKE2b-256 ec95cb885b43e43ebe5a055f9a2aa0c05f7ebc9c326af2e6a78545a3c275390d

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on GonzaloFuentes28/video-mosaic

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