About
Generates video preview thumbnails for Plex, Emby, and Jellyfin. These are the small images you see when scrubbing through videos in any of those servers.
The Problem: Built-in preview generation has gaps depending on the server you run:
- Plex generates thumbnails single-threaded on the CPU (no GPU support).
- Emby has no GPU support for thumbnail generation at all.
- Jellyfin does support hardware-accelerated trickplay, but it shares CPU/GPU with playback — and on a busy server that’s resources you’d rather give to the player.
The Solution: This tool runs preview generation off the media server on a machine of your choosing, uses every GPU it finds, and processes files in parallel. When two or more servers contain the same file, FFmpeg runs only once — the result is then written out in each server’s own expected format, automatically.
This project was originally hand-written. Recent development is AI-assisted (Cursor + Claude). All changes are reviewed and tested.
Features
One FFmpeg pass, every server. Point it at Plex, Emby, Jellyfin — any mix,
any number — and a single generation run writes the right output format to each
(Plex BIF bundle, Emby sidecar BIF, Jellyfin trickplay tiles). See the
multi-server guide for how the dispatcher routes one
file to every server that owns it.
Automation that just works. Radarr / Sonarr / Tdarr / FileFlows webhooks,
Plex direct (Plex Pass), Recently Added polling, cron & interval schedules —
all share one universal inbound URL with vendor auto-detection. A 5-step
backoff retry (30 s → 2 m → 5 m → 15 m → 60 m) handles files your server
hasn’t indexed yet. Source-aware dedup re-runs automatically when a file is
swapped (e.g. a Sonarr/Radarr quality upgrade) and skips when nothing changed.
Need to (re)generate something by hand? Manual Generation lets you search
your servers by title — pick a show to cover every episode, or a movie, episode,
folder, or single file — or browse your media tree, no path-typing required.
Hardware you already have. NVIDIA, AMD, Intel — per-GPU worker counts and
FFmpeg threads, automatic in-place CPU retry if a codec fails on the GPU, and
HDR / Dolby Vision tone mapping (including Profile 5 via libplacebo). A
Previews Readiness panel on each server audits every flag that affects
whether your previews actually show up, with one-click toggles and typed
confirmation for destructive changes.
Screenshots
Quick Start
Docker (Recommended)
docker run -d \
--name media-preview-generator \
--restart unless-stopped \
-p 8080:8080 \
--device /dev/dri:/dev/dri \
-e PUID=1000 \
-e PGID=1000 \
-v /path/to/media:/media:ro \
-v /path/to/plex/config:/plex:rw \
-v /path/to/app/config:/config:rw \
-v /etc/localtime:/etc/localtime:ro \
stevezzau/media_preview_generator:latest
Replace /path/to/media, /path/to/plex/config, and /path/to/app/config with your actual paths.
Timezone: The /etc/localtime mount ensures log timestamps and scheduled jobs use your local time. Alternatively, use -e TZ=America/New_York (replace with your timezone).
Then open http://YOUR_IP:8080, retrieve the authentication token from container logs, and complete the setup wizard.
For Docker Compose, Unraid, and GPU-specific setup:
Installation
- Web UI only: The Docker image runs the web interface. There is no CLI; all configuration and job management is done via the web UI.
- PyPI: The package is no longer published on PyPI; use Docker or install from source.
[!IMPORTANT]
The Docker Hub image is published as stevezzau/media_preview_generator — the double z is the author’s Docker Hub username (not a typo).
stevezzau/media_preview_generator on Docker Hub.
GPU Support
| Platform |
Supported GPUs |
Via |
| Linux (Docker) |
NVIDIA, AMD, Intel |
CUDA/NVENC, VAAPI, QuickSync |
| Windows (native) |
NVIDIA, AMD, Intel |
CUDA, D3D11VA |
| macOS (native) |
Apple Silicon, Intel |
VideoToolbox |
| Linux / Windows / macOS |
No GPU |
CPU workers only |
On Docker Desktop (Windows/WSL2 and macOS) the container runs inside a Linux VM, so D3D11VA and VideoToolbox aren’t reachable — Docker on those platforms processes on CPU. For GPU acceleration on Windows or macOS, install from source.
See Getting Started — GPU Acceleration for per-vendor setup, tuning, and detection. Detected GPUs are shown in the web UI under Settings or Setup.
GPU + CPU Fallback
CPU fallback is automatic and built into every GPU worker — there is no separate “fallback” pool to configure. If a file fails on the GPU for any reason (unsupported codec, hardware error, driver crash), the same worker automatically retries it on the CPU and the dashboard shows a yellow CPU fallback badge so you know it happened.
If you have a lot of content that never decodes on the GPU, raise CPU Workers above 0 so that those files route straight to dedicated CPU workers instead of blocking a GPU worker each time.
See Automatic GPU → CPU Fallback for details.
Documentation
| Document |
What’s there |
| Documentation Hub |
Pick the right doc for your task |
| Getting Started |
Install with Docker, GPU setup, Unraid, networking |
| Guides |
Web UI, schedules, webhooks, HDR handling, troubleshooting |
| Reference |
Config options, env vars, REST API, WebSocket events |
| FAQ |
Common questions about setup, performance, and compatibility |
Built With
Contributing
Contributions are welcome. See CONTRIBUTING.md for local setup, tests, code style, and the PR workflow.
License
Distributed under the MIT License. See LICENSE for details.
Acknowledgments
- Plex for the media server
- FFmpeg for video processing
- LinuxServer.io for the Docker base image
- Rich for beautiful terminal output
- All contributors and users
Made with care by stevezau
Star this repo if you find it useful!
评论