Your media server's slowest jobs, done on your GPU

Media Preview Generator makes the preview thumbnails and the Skip Intro and Skip Credits markers for Plex, Emby and Jellyfin. It starts the moment Sonarr or Radarr imports a file and sends the results to every server at once. The GPU can be in another machine.

One Docker container Plex, Emby and Jellyfin CPU fallback built in Needs write access where previews live

Plex's web player paused on Tears of Steel, the pointer on the seek bar at 5:07 and a preview thumbnail of that scene above it
Plex's web player on a test server, mid-scrub. The thumbnail above the timeline came from this app. Tears of Steel, (CC) Blender Foundation | mango.blender.org, CC BY 3.0.
The problem

The built-in generators fall behind

Plex, Emby and Jellyfin can make these thumbnails themselves. They do it inside the media server, mostly on the CPU, and mostly on a schedule; Plex's own help page warns that a large library can take days. Until then, the episode that arrived on Friday night has a timeline with no pictures on it, and finding the scene where you fell asleep means guessing.

Media Preview Generator does the job on the GPU, one file at a time, as each file arrives.

How it works

From a new file to a preview on every server

You set it up once. After that, every new file goes through these five steps on its own.

A new file arrives

Sonarr, Radarr, Tdarr or the media server itself sends a webhook when a file lands, to the URL the Automation page gives it. Scheduled scans and a hand-picked list work too.

192.168.1.10:8080/automation
The Automation page's *arr apps card with Sonarr, Radarr and Sportarr tabs, a Publish to which server? choice and the Sonarr webhook URL

It finds every server with that file

The path Sonarr reports is mapped to the path the container sees. Then every Plex, Emby and Jellyfin library that holds the file is found.

192.168.1.10:8080/servers
The Servers page with one card each for Home Plex, Home Jellyfin and Home Emby, each showing its address and enabled libraries

One GPU pass per file

FFmpeg decodes the video on the GPU, jumps between key frames when the file allows it, and tone-maps HDR. The GPU can be in another machine. If one GPU can't decode a file, your other GPUs try it, then the CPU.

192.168.1.10:8080/
Workers panel as a table: busy GPU and CPU workers with percent, speed and ETA, idle workers folded into one line, and a worker group on the gpu-box node

Each server gets its own format

A BIF in Plex's data folder, a BIF next to the video for Emby, trickplay tiles for Jellyfin. Then each server is told to pick them up.

192.168.1.10:8080/
A completed job's details with the Files tab open: one file marked Generated, with Home Plex, Home Jellyfin and Home Emby listed as its servers

It waits for slow servers

A server that hasn't indexed the new file yet gets another try after 1, 2, 5, 15 and 60 minutes by default. Next time, files whose previews are current are skipped.

192.168.1.10:8080/
The Jobs queue with four rows: Tears of Steel running at 62%, Sintel pending with Retry 2/5 and Retry starting in 4 min, Big Buck Bunny completed, and Elephants Dream pending
  • 1

    decode per file

    Several servers hold the same file? It is read once, and each server gets its own format.

  • 3

    media servers

    Plex, Emby and Jellyfin, in any mix, from one container.

  • 1

    webhook URL

    Sonarr, Radarr, Plex, Emby and Jellyfin can all post to the same address. The app works out who sent it.

Choose your setup path

One file, three servers

Plex, Jellyfin and Emby from one decode

Run more than one server and the app reads each file once, then writes what each one expects: a BIF for Plex, a BIF next to the video for Emby, trickplay tiles for Jellyfin.

Tears of Steel in the Plex, Jellyfin and Emby web players, each showing a preview thumbnail over the seek bar
The same film on three test servers, each scrubbed to the same point. Full size: Plex, Jellyfin, Emby. Tears of Steel, (CC) Blender Foundation | mango.blender.org, CC BY 3.0.
HDR and Dolby Vision

Previews in normal colour, not grey or green

A frame grabbed from HDR video without tone mapping comes out flat and grey, and Dolby Vision can come out green. The app tone-maps HDR10, HLG and HDR10+, and uses the HDR10 layer of Dolby Vision profiles 7 and 8. Profile 5 needs a GPU with a hardware Vulkan driver.

The same HDR frame twice: grey and flat without tone mapping, natural colour from this app
The same moment of Cosmos Laundromat in HDR: left, a plain FFmpeg frame grab; right, the frame from the preview file this app made. Cosmos Laundromat, an Open Movie project created by Blender Studio and directed by Mathieu Auvray; HDR re-grade by Netflix with Blender Foundation and Fotokem's Keep Me Posted (Netflix Open Content), CC BY 4.0.

HDR and Dolby Vision in detail

Features

What you get

GPU first, CPU when needed

NVIDIA, Intel and AMD on Linux; NVIDIA on Windows through WSL2. Add GPUs from other machines as worker nodes. A file one GPU can't decode goes to your other GPUs first, then the CPU.

Use another machine's GPU

Starts per file

Sonarr, Radarr, Sportarr, Tdarr, FileFlows, Plex, Emby and Jellyfin webhooks, or any JSON with a path. A new episode gets its previews without waiting for a nightly task.

One decode, every server

With Plex and Jellyfin on the same library, each file is read once and both servers get their own output.

Skips what's already done

Each preview is matched to the file it came from. A quality upgrade from Radarr is redone; an untouched file is skipped, even after a remount or a move.

Says why previews don't show

Setup Health checks each server's settings, explains the ones that stop previews appearing, and offers to fix them one library at a time.

Skip Intro and Skip Credits

Finds intros and end credits from the file's chapters, online skip databases, the season's theme song or the credit roll itself, then sends the markers to every server. When it isn't sure, it sends nothing instead of a guess.

What each server needs
Works with

What goes in, and what comes out

Something new arrives

Sonarr · Radarr · Tdarr · server webhooks · schedules

One GPU decode

NVIDIA, Intel or AMD, or the CPU, on this machine or another

Each server's own format

Plex BIF · Emby BIF · Jellyfin trickplay

Only a media server and Docker are required. Everything else is used if you already run it.

Required

  • Plex, Emby or Jellyfinany mix; Jellyfin 10.10 or newer
  • Dockerlinux/amd64 or linux/arm64, Unraid template included
  • Write access where previews livePlex's data folder, or the media folder for Emby and Jellyfin

GPUs (optional)

  • NVIDIACUDA decoding, also on Windows through WSL2
  • Intel and AMDVAAPI decoding on Linux
  • Another machine's GPUadded as a worker node
  • No GPUCPU workers do the same job

Automation (optional)

  • Sonarr and Radarrimport and upgrade webhooks
  • Tdarr and FileFlowsa webhook after each transcode
  • The servers themselvesPlex (Plex Pass), Emby (Premiere) and Jellyfin webhooks, or Recently Added polling

Skip Intro and Skip Credits, per server:

  • PlexNeeds Plex Pass on the server, and for viewers (or their Plex Home); the app runs on the Plex machine, or next to it through a Plex database node (also for Plex on Windows).
  • JellyfinJellyfin 10.11 or 12.0 with the Media Preview Bridge plugin (the one trickplay uses).
  • EmbyEmby 4.9 or 4.10 with the Media Preview Bridge for Emby plugin; Skip Intro needs Emby Premiere, Skip Credits doesn't.
Compared with the built-ins

Keep the built-in if it keeps up

The generators in Plex, Emby and Jellyfin need no setup and cost nothing extra. This app is for when they don't keep up with your library, and it costs some setup: a container, GPU passthrough, and write access to where each server keeps its previews.

See the side-by-side comparison

Quick start

Start the container, open the web UI

Open http://your-server:8080, log in with the token saved in auth.json in your app config folder (or your own, set with WEB_AUTH_TOKEN), and the setup wizard connects your servers.

docker-compose.yml
# docker-compose.yml: set the paths, then docker compose up -d
services:
  media-preview-generator:
    image: stevezzau/media_preview_generator:latest
    container_name: media-preview-generator
    restart: unless-stopped
    ports:
      - "8080:8080"
    devices:
      - /dev/dri:/dev/dri  # Intel or AMD GPU; delete both lines if you have none
    # NVIDIA: delete the two lines above, uncomment these five
    # deploy:
    #   resources:
    #     reservations:
    #       devices:
    #         - {driver: nvidia, count: all, capabilities: [gpu]}
    environment:
      - PUID=1000
      - PGID=1000
      # - NVIDIA_DRIVER_CAPABILITIES=all  # NVIDIA
    volumes:
      - /path/to/media:/media  # can be :ro if you only run Plex
      - /path/to/plex/config:/plex
      - /path/to/app/config:/config
docker run
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 \
  -v /path/to/plex/config:/plex \
  -v /path/to/app/config:/config \
  stevezzau/media_preview_generator:latest

NVIDIA with docker run? Use --gpus all -e NVIDIA_DRIVER_CAPABILITIES=all instead of --device /dev/dri. No GPU, or on Windows or macOS? Delete the --device /dev/dri line (in compose, the two devices lines). Plex needs its data folder read-write; Emby and Jellyfin need the media folder read-write. Full requirements →

Questions

Common questions

Why are my Plex preview thumbnails taking so long?

Plex makes them inside the server, on the CPU, one frame every 2 seconds by default, during its scheduled maintenance window and optionally when media is added. Plex's own help page says a large library can take days. You can space the frames out in Plex, or hand the job to a GPU with this app, which starts on each file as it arrives. More

Can I generate Plex preview thumbnails with a GPU?

Not with Plex itself: Plex documents no GPU option for this job. Media Preview Generator runs it with FFmpeg on an NVIDIA, Intel or AMD GPU and writes the result where Plex expects it, in Plex's data folder, which it needs read-write. More

How do I make Jellyfin trickplay generation faster?

Start with Jellyfin's own settings: hardware decoding, key-frame-only extraction, and more FFmpeg threads than the default of 1. If it still falls behind, this app can make the trickplay tiles on a GPU, on another machine if you like, and tell Jellyfin about them. More

Does Emby's thumbnail extraction use the GPU?

No. Emby's built-in BIF extraction has no GPU option. This app makes Emby BIF files on a GPU and saves them next to each video, where Emby looks for them, so the media folder must be writable. More

Can previews be made as soon as Sonarr or Radarr imports a file?

Yes. Add a webhook in Sonarr or Radarr for import and upgrade. The app waits for a quiet period (60 seconds by default), makes the previews, and retries while the media server is still indexing the new file. More

Why are my HDR or Dolby Vision preview thumbnails washed out or green?

The frames were grabbed without tone mapping, so HDR colours land in an ordinary picture. This app tone-maps HDR10, HLG and HDR10+, and uses the HDR10 layer of Dolby Vision profiles 7 and 8. Profile 5 needs a GPU with a hardware Vulkan driver in the container. More

Do I need a GPU to use Media Preview Generator?

No. Without one it runs on CPU workers; set how many in Settings → Workers. With a GPU, decoding moves off the CPU. A file one GPU can't decode goes to your other GPUs first, then the CPU.

Does it run on Windows or Unraid?

Yes, in Docker. There is an Unraid Community Applications template. On Windows (Docker Desktop with WSL2) only NVIDIA GPUs are used; Intel and AMD GPUs there, and everything on macOS, run on the CPU. A Plex installed on Windows needs a Plex database node beside it for Intro & Credits. More

Read the full FAQ

Give it a try

It's free and MIT licensed. If something doesn't work, open an issue and say what you tried.

Type to search the documentation.