Blazing-fast 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. 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, 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).
Current scope:
- Image thumbnails are production ready (Pillow fallback + libvips optional).
- Async helper delegates to the active backend (libvips or Pillow).
- Video thumbnail extraction is not yet implemented; a stub is exported so the public API stays stable.
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.
Getting Started
Clone the repository and create a virtual environment from your system Python:
git clone https://github.com/chrisppa/thumbnail-generator.git
cd thumbnail-generator
python3 -m venv venv # use /usr/bin/python3 on Linux
source venv/bin/activate # .\venv\Scripts\activate on Windows
pip install -U pip
Install dependencies:
# Pillow backend (default)
pip install -e .
# Add libvips support
pip install -e .[vips]
To run the CLI anywhere in the project, keep the environment activated:
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 (planned)
thumbnail_generator.video_thumbnail_from_url() currently raises NotImplementedError. The stub exists so the import surface is ready when ffmpeg integration lands.
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. -
NotImplementedErrorfor video
Video thumbnailing is on the roadmap; the current placeholder signals that this API surface is reserved. -
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.
- Video frame extraction using ffmpeg-python.
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.1.0.tar.gz.
File metadata
- Download URL: thumbnail_generator-0.1.0.tar.gz
- Upload date:
- Size: 6.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea7e201bcbe6025fad8f2359c8f585f225bd9e1b3b37bbdceb02ff0dd12ae1a9
|
|
| MD5 |
4e1ecd18b3877110b9027507b4104900
|
|
| BLAKE2b-256 |
c8a3da516ce30dfaa049703cd374ab041de58fe339981dd673c5655e0f8e010b
|
File details
Details for the file thumbnail_generator-0.1.0-py3-none-any.whl.
File metadata
- Download URL: thumbnail_generator-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fc621dbebd92e45a1d5b6d87b6c9b316ed81bbd1abd085fe72c7f58ff461887
|
|
| MD5 |
8e32e4d640a6b37400cc5afd2c864191
|
|
| BLAKE2b-256 |
e74979346b2ffcb4e922f9845a5d5e12cb3504045a897708d4162172adb141ee
|