GPU-accelerated tool that generates Plex video preview thumbnails much faster

Hey everyone,

A while ago I built a tool to speed up the generation of video preview thumbnails (the images you see when scrubbing through a video on the timeline). Why? Because on a large library it can take many days since Plex’s built-in approach is CPU only.

Recently it’s been upgraded with a web UI and integration with Sonarr/Radarr/Tdarr. I’ve never posted it anywhere so I thought I’d share it here in case others find it useful.

----------------------

Plex Generate Previews - uses your GPU (NVIDIA, AMD, Intel, or even Apple Silicon) to generate BIF files way faster. On my setup it’s roughly 5-10x quicker than Plex.

What it does:

- GPU-accelerated thumbnail extraction via FFmpeg (CUDA, VAAPI, QuickSync, D3D11VA, VideoToolbox)

- Configurable parallel GPU + CPU worker threads

- Web dashboard for managing jobs, schedules, and settings

- Radarr/Sonarr webhook integration — new media gets thumbnails automatically

- Custom webhook endpoint for Tdarr or any external tool

- Cron and interval scheduling so you can set it and forget it

- CPU-only mode if you don’t have a GPU

- Docker image with a setup wizard

Links:

- GitHub: https://github.com/stevezau/plex_generate_vid_previews

- Docker Hub: https://hub.docker.com/r/stevezzau/plex_generate_vid_previews

- Docs: https://github.com/stevezau/plex_generate_vid_previews/blob/main/docs/getting-started.md

Omg… you’re the developer? Thank you for making it. That really helped me out a lot when I changed the Plex GenerateBIFFrameInterval to 10. I had to scrap all the previews and start over.

I talked about your script 3 years ago on reddit.

I can’t believe there’s now a UI. That’s awesome!

Glad it helped!

Hi Steve, if once generated with your script, can I safely turn on the Plex generation?

Hi @andreasmaks if you meant turn it off, yes you can. You can also leave it on as Plex will skip if they already exist.

Hi @stevezau, no, I meant turn off your script and let plex generate the thumbnails for new entries afterwards.
First your fast script → then the Plex default generation.

Yes, that will work. This tool follows the same process Plex does, you can use either at any time.

Hi, I just got your app running on my Unraid machine. It’s very easy-to-use. UI is clean and instructions are all very clearly written. I was able to follow through installation without much hiccup. :+1:

My Unraid server has a Intel® Core™ Ultra 7 255H and I’m able to use quicksync hardware acceleration without issue. The problem is that all thumbnail previews I’ve generated are wildly out of sync when I play them on Plex. They are about 4-5x slower than the actual movie. Meaning, when the movie is at 1:00:00 mark, the thumbnails are still showing 15:00~20:00.

It doesn’t matter if I use CPU or GPU. Doesn’t matter which movie/what codec the movie is in. The same issue persists. When I go to finished jobs to look at the results in preview inspector, the thumbnail previews are fine-- and they cover the whole movie. They also get “published” to my Plex server just fine. But when I watch this movie in Plex-- the thumbnail preview timing is all wrong.

I’m on version 4.3 of Media Preview Generator and PMS version 1.43.3.10793. Any help? Thanks in advance.

Here I’m using Annihilation for testing purposes because it has very recognizable chapter title cards. I can confirm that the thumbnail preview is generated correctly as far as I can tell because chapter title cards, like this one later in the film, all appear to be in the right place. So I’m really at a loss why it plays out of sync with the movie itself in Plex.

The only thing I can think of is, here I’m using 5s interval. Is the 05:45:00 supposed to match the length of the movie? The actual movie is only 01:55:00 long. So that’s precisely 3 times its length. Could this be the problem?

@stevezau log attached.

job-bc8f8862-658c-4d21-8d70-b9604c393eda-logs.txt (10.5 KB)

Thanks for the detailed report and the log I think you’ve found a bug…

The tool builds a strip of preview thumbnails and tells Plex they’re spaced 5 seconds apart. On your Dolby Vision file it accidentally grabbed about 3× too many frames (roughly one every 1.7s
instead of every 5s) but still labelled them “5s apart.” So Plex thinks the preview strip is 3× longer than the movie — scrub to the end of the film and it shows a thumbnail from only ~40 minutes in. That’s the drift you’re seeing, and it’s why it happens on both CPU and GPU (it’s a frame-count problem, not a decoding one).

The tell is right in your log: 4,141 thumbnails for a 1h55m movie at 5s spacing = 5h45m of previews — exactly 3× too long, which matches the “05:45:00” you spotted. Normal HDR10 and single-layer Dolby Vision files come out fine — it’s the dual-layer Dolby Vision (Profile 7) format specifically that’s tripping up the frame grabber.

I will ship a fix.. but to make sure I ship the right one, could you run this quick test on that Annihilation file? It tells me whether the fix is simple or needs deeper Dolby Vision handling. Replace CONTAINER with your container name (find it with docker ps):

docker exec CONTAINER sh -c '
F=/usr/lib/jellyfin-ffmpeg/ffmpeg
IN="/media/Films/Annihilation (2018)/Annihilation (2018) Bluray-2160p {imdb-tt2798920}.mkv"
echo "== Dolby Vision profile =="
ffprobe -v error -select_streams v:0 -show_frames -read_intervals "%+#1"
-show_entries frame=side_data_list "$IN" 2>/dev/null | grep -iE "dv_profile|dv_bl|dolby"
echo "== frame sampling at 5s =="
$F -v error -i "$IN" -vf "fps=1/5,showinfo" -f null - 2>&1
| grep -oE "pts_time:[0-9.]+" > /tmp/pts.txt
echo "frames extracted: $(wc -l < /tmp/pts.txt)   (expected ~1380)"
echo "first frame: $(head -1 /tmp/pts.txt)"
echo "last frame : $(tail -1 /tmp/pts.txt)   (expected ~6900)"
'

Paste the output back. In short: if it shows ~4,100 frames but the last timestamp is still ~6,900, the fix is simple. Thanks again for chasing this one down — really helpful. :folded_hands:

My NAS CPU fires up to 100% but I never received an output. I have to stop the container after a good 10 minutes. Not sure if You have to specify one input file means the file path is wrong. I tried to use /mnt/user/media and /data/ but same result. There’s no file not found error or anything like that.

I ran the app on more movies. It generated previews for 2046 and Beau Travail correctly-- the previews play in Plex without issues.

job-a9252795-3ed0-44f1-be04-f2f79a4f3e9f-logs.txt (6.7 KB)

job-19820a89-af54-404a-8b4e-b4765f473b8c-logs.txt (6.8 KB)

But most previews generated have the same issue I described from above. Not sure if it’s Dolby Vision related because it happens on seemingly the most basic h.264 encode as well. Here’s an example:

job-a86c6a55-bcf9-41c6-87fb-86fb86d155fe-logs.txt (6.5 KB)

The length of previews for all three of these movies appear to be correct i.e. same as movie runtime in the preview inspector, unlike Annihilation. But, only the previews for 2046 and Beau Travail worked in Plex. I’m struggling to understand the common denominator of the issue here. Hope this helps.

Hi @Bjoure , I THINK i know what the bug is but i am trying to reproduce locally.

Would you be able to share the exact filename you have so i can try find it also (DM me if you like)..

In addition if you can run the below so i can understand the exact codecs this file uses.

docker exec media-preview-generator /usr/lib/jellyfin-ffmpeg/ffprobe -v error \
    -select_streams v:0 -show_entries stream_side_data=dv_profile -of csv=p=0 \
    "/media/Films/Annihilation (2018)/Annihilation (2018) Bluray-2160p {imdb-tt2798920}.mkv"

It should.

  • Prints 7 → it’s dual-layer FEL; then a real REMUX.. reproduces it and I proceed.
  • Prints 8 (or 5) → my P7 theory is wrong, and we re-open the investigation with the right target instead of chasing remuxes.

The output is 8.