Thumbnail generator from image/video URLs (pyvips primary + Pillow fallback)
Project description
thumbnail-generator
thumbnail-generator is a tiny, modern toolkit for creating thumbnails directly from remote image URLs and videos. It streams the source file, transforms it entirely in memory, and returns ready-to-serve bytes. The library powers a Python API, an async helper, video helpers, and a Typer-based CLI. Pillow is used out of the box; drop in pyvips for big speed wins with constant memory usage.
Project Highlights
- Stream thumbnails straight from HTTPS URLs without writing to disk.
- Automatic EXIF orientation correction and high-quality downsampling.
- Unified crop modes:
fit,fill,pad, andsmart(smart switches to libvips smartcrop when available). - Multiple output formats (
JPEG,WEBP,AVIF,PNG) with adjustable quality. - Async helper for event-driven crawlers.
- CLI command for quick batch jobs or scripting.
- Optional libvips backend (5–10× faster than Pillow on large images).
- Optional ffmpeg-powered video thumbnails that reuse the same image pipeline.
Current scope:
- Image thumbnails are production ready (Pillow fallback + libvips optional).
- Async helper delegates to the active backend (libvips or Pillow).
- Video thumbnail extraction works via ffmpeg (install with
[video]extra and ensure the ffmpeg binary is on PATH).
Requirements
- Python 3.9 or newer (repository is tested with Python 3.12).
- Linux, macOS, or Windows.
- Optional: system
libvipsif you plan to use the high-performance backend.- Ubuntu/Debian:
sudo apt install libvips - macOS:
brew install vips - Windows: install the prebuilt libvips bundle from libvips releases and add it to
PATH.
- Ubuntu/Debian:
Note on Anaconda: when using libvips, keep Python and the native libraries from the same toolchain. Mixing a conda-based Python with system
libvipsoften results in loader errors. Creating a virtual environment from/usr/bin/python3(Linux/macOS) or using a clean conda environment that installslibvipsfrom conda-forge solves this.
Installation
PyPI (recommended)
pip install thumbnail-generator
Upgrade anytime:
pip install --upgrade thumbnail-generator
For the high-performance libvips backend (5–10× faster at large resolutions):
pip install thumbnail-generator[vips]
Make sure the native libvips shared library is available (e.g. apt install libvips, brew install vips, or conda install -c conda-forge libvips pyvips). If libvips cannot be imported the package automatically falls back to Pillow and prints using pillow backend when you run the CLI.
The CLI depends on Typer and is bundled automatically from version 0.1.1 onward. If you are on 0.1.0, run pip install typer once or upgrade: pip install --upgrade thumbnail-generator.
Enable video thumbnails (requires the ffmpeg binary and ffmpeg-python binding):
pip install thumbnail-generator[video]
Ensure the ffmpeg executable is available on your PATH (Linux/macOS: sudo apt install ffmpeg / brew install ffmpeg; Windows: install the static build from https://ffmpeg.org/download.html and add its bin/ directory to PATH).
From Source
git clone https://github.com/chrisppa/thumbnail-generator.git
cd thumbnail-generator
python3 -m venv venv # /usr/bin/python3 on Linux
source venv/bin/activate # .\venv\Scripts\activate on Windows
pip install -U pip
pip install -e . # Pillow backend
pip install -e .[vips] # Optional libvips backend
Keep the virtual environment active whenever you run the CLI or tests:
source venv/bin/activate
Usage
CLI
thumbnail-generator https://images.unsplash.com/photo-1682687220742-aba13b6e50ba \
--size 800x800 \
--crop smart \
--format WEBP \
--output hero.webp
Options (via thumbnail-generator --help):
--output– destination file path (defaultthumb.jpg).--size–<width>x<height>integers (default400x400).--crop– one offit,fill,smart,pad.--format–JPEG,WEBP,AVIF,PNG.--quality– integer 1–100 (backend-specific defaults to 90).
When pyvips is available the CLI reports Saved … using vips backend, otherwise Pillow is used automatically.
Python API
from thumbnail_generator import thumbnail_from_url, CropMode
buf = thumbnail_from_url(
"https://example.com/large.jpeg",
size=(500, 300),
crop=CropMode.FILL,
format="WEBP",
quality=85,
)
with open("thumb.webp", "wb") as fp:
fp.write(buf.getvalue())
Async API
import asyncio
from thumbnail_generator import athumbnail_from_url
async def main():
buf = await athumbnail_from_url(
"https://example.com/scene.jpg",
size=(320, 320),
)
with open("async-thumb.jpg", "wb") as fp:
fp.write(buf.getbuffer())
asyncio.run(main())
The async helper uses the currently active backend under the hood.
Video API
from thumbnail_generator import video_thumbnail_from_url, CropMode
thumb = video_thumbnail_from_url(
"https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
size=(640, 360),
crop=CropMode.FILL,
format="WEBP",
)
with open("video-thumb.webp", "wb") as fp:
fp.write(thumb.getvalue())
Install with pip install thumbnail-generator[video] and ensure the ffmpeg binary is available. The helper samples multiple timestamps and reuses the active image backend for resizing/cropping.
Backends Explained
| Backend | Activation | Strengths | Notes |
|---|---|---|---|
| Pillow | Installed automatically with pip install -e . |
Zero native deps, works everywhere | Best for small/medium images |
| libvips | Install libvips + pip install -e .[vips] |
Fast, constant memory, smart cropping available | Requires OS-level libvips libraries |
CropMode.FIT: fits inside the target box, preserving aspect ratio.CropMode.FILL: fills the target box by scaling and center-cropping.CropMode.SMART: same asFILL; if libvips is active, switches tosmartcrop.CropMode.PAD: letterboxes the image on a background color.
Output formats are passed straight to the backend. The default quality is 90; adjust for smaller files or higher fidelity.
Development Workflow
source venv/bin/activate
pip install -e .[dev,vips] # add dev extras when they land
pytest # once the test suite is added
python -m thumbnail_generator.cli --help
Recommended extras (when available) include Ruff for linting, Mypy for typing, and pytest with responses for mocking HTTP downloads.
Troubleshooting
-
ImportError: cannot load library 'libvips.so.42'
Ensurelibvipsis installed system-wide and that your Python runtime comes from the same toolchain. Recreate the virtualenv with/usr/bin/python3or use a dedicated conda env withconda install -c conda-forge libvips. -
PyPI install without libvips
If you install the package elsewhere and want to force Pillow, omit the[vips]extra orpip uninstall pyvips. -
Video thumbnails fail:
ffmpegnot found
Install the[video]extra (pip install thumbnail-generator[video]) and ensure theffmpegexecutable is discoverable on PATH. On Windows, download a static build and restart your shell after updating PATH. -
Timeouts fetching images
The default HTTP timeout is 30 seconds. If you need retries, wrapthumbnail_from_urlin your own retry logic or extendDEFAULT_HEADERS/DEFAULT_TIMEOUTincore.py.
Roadmap
- Smart crop improvements (face/saliency detection fallback when Pillow is active).
- Configurable caching (memory/disk).
- CLI batch mode with globbing and progress indicators.
- Intelligent frame scoring (sharpness / aesthetic ranking) for video thumbnails.
License
MIT © chrisppa
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file thumbnail_generator-0.2.0.tar.gz.
File metadata
- Download URL: thumbnail_generator-0.2.0.tar.gz
- Upload date:
- Size: 7.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fcd862637a2e037daff6a0847a7cb1104b6b6680d715a5c1ce3b2ec6e2085f4
|
|
| MD5 |
56b3fa57f5e78129b4079b7d79336b5c
|
|
| BLAKE2b-256 |
90d5e8e21f4a9d072fee691baf745744ce0e82f8fc35ad7e6d2ed38a729adf92
|
File details
Details for the file thumbnail_generator-0.2.0-py3-none-any.whl.
File metadata
- Download URL: thumbnail_generator-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dca61e412daef5135acb795f953e66bc47276c89ec52574a5473fd0c3536aa4
|
|
| MD5 |
3c1d2d399ad627b5c94dc83cbe992168
|
|
| BLAKE2b-256 |
772c0cd485c71072c25079304468fe4c385e65520886d4087aec96f625e4c03b
|