Thumbnails & Screenshots using FFmpeg – 3 Efficient Techniques

There are several easy ways to take screenshots/thumbnails of movies using FFmpeg. But why do this in the first place?

  1. You might want to generate thumbnails for your videos and show those thumbnails to the user when he scrolls through the video.
  2. Or, you might want to compare two videos by doing a side-by-side comparison – this is quite common in video compression research.

FFmpeg offers very simple techniques to extract screenshots or thumbnails at any position of the video (or rather, a way to dump frames at any point you choose).

Let’s see how!

Single Screenshot/Thumbnail Using -frames:v

First, let’s understand how to take a single screenshot or thumbnail using FFmpeg.

ffmpeg -i inputvideo.mp4 -ss 00:00:03 -frames:v 1 foobar.jpeg

Understanding this is very simple! Here goes –

  1. -ss is the seek command and it can be used to seek to the right position. For accurate seeking, you need to use output seeking and not input seeking (i.e., putting -ss before the input sequence). The syntax for specifying the time is HH:MM:SS.MILLISECONDS. For example, you can tell FFmpeg to seek to 01:02:03 – i.e., the 3rd second of the 2nd minute of the 1 hour of the movie!
  2. -frames:v 1 tells FFmpeg to take only 1 screenshot. Note that, -vframes is deprecated.
  3. then, you mention the name of the output file (screenshot_10.jpg).

Simple, wasn’t it? Now that you know how to produce a single thumbnail or screenshot, let’s move to the next section where we understand how to create regular or periodic thumbnails.

Periodic Screenshot/Thumbnail with Resizing

Here is another common use case that FFmpeg can solve easily – how do you take screenshots/thumbnails at regular intervals, and store them to JPG files after resizing them?

Here is a simple one-liner that can take care of creating a thumbnail and resizing it for you.

ffmpeg -i input1080p.mp4 -r 1 -s 1280x720 -f image2 screenshot-%03d.jpg

The -r command sets the output frame rate (=1) and image2 is an image file muxer that is used to write video frames to image files. Using the -s 1280x720 command, we can resize the video frames before writing them as images. Note, that the input video is a 1920x1080p video.

The above command will take a screenshot every 1 second. The screenshots would be named 001, 002, etc. because we have specified the formatting as %3d.

However, in my experience, I have found this technique to be not frame-accurate.

Related:  Convert to YUV using FFmpeg and Playback Using ffplay

In the next section, let’s look at a more accurate way of extracting thumbnails.

Screenshot/Thumbnail every 10 seconds

As an extension of the previous section, let’s do a quick exercise and learn how to create a thumbnail every 10 seconds using FFmpeg.

ffmpeg -i inputvideo.mp4 -vf "select='not(mod(n,300))',setpts='N/(30*TB)'" -f image2 thumbnail%03d.jpg


  1. we use the select filter to extract a frame if the expression in single-quotes evaluates to non-zero. If the expression is zero, then select filter discards that frame.
  2. mod(A,B) returns the modulus (remainder after division) result after dividing A by B. So, if we divide 0 by 300, we get 0. Then, 1/300 is 1, and so on.
  3. not inverts this result. So, if the modulus is zero, then the final result is 1. If the modulus is non-zero, then the result is evaluated to zero.
  4. Based on this not operation, the select filter picks up a frame.

The sequence I am using has a frame-rate of 30 fps. And, I want a frame every 10 seconds. So, I have to choose a frame out of every 300 frames, right? That is why I used select='not(mod(n,300))'

This gives me very accurate thumbnails as you can see in the image gallery below. Click on the images to expand them and see the timestamps.

Depending on your sequence’s frame-rate, you can modify the command line shown. If you don’t know your video’s frame-rate, you can use ffprobe to find out.

ffprobe -show_entries format=duration globe-with-timestamp.mp4


There you have it – multiple easy ways to generate thumbnails and screenshots using FFmpeg. You can choose to take single screenshots or periodic ones with a highly frame-accurate technique!

Until next time, take care and don’t forget to share this article and check out the rest of the news, articles, and tutorials on

krishna rao vijayanagar
Krishna Rao Vijayanagar

Krishna Rao Vijayanagar, Ph.D. is the Editor-in-Chief of OTTVerse, a news portal covering technological and business news in the OTT space. With extensive experience in video compression, ABR streaming, video analytics, monetization, and more, Krishna has held multiple roles in R&D, Engineering, and Product ownership at companies such as Harmonic Inc., MediaMelon, and Airtel Digital. Krishna has published numerous articles and research papers on the latest trends in OTT and frequently speaks at industry events to share his insights and perspectives on the fundamentals and the future of OTT streaming.

4 thoughts on “Thumbnails & Screenshots using FFmpeg – 3 Efficient Techniques”

  1. Great answer thanks – fixed my thumbs problem – but please you could explain what setpts is doing and should it always be setpts=’N/(30*TB)’ or does this depend on framerate?

  2. Works perfectly if the frame rate is a standard integer. If the frame rate is an awkward 29.98 (as is being reported by one of my videos) it does not work.

  3. In relation to my above comment, of course you could round it to 30, but if the thumbs would then remain dead on accurate, I am not sure. My code ended up as follows (for now):

    let vf
    if (probeResponse.fps === Math.round(probeResponse.fps)) {
    // the preferred approach but it only works if fps is an integer
    vf = `-vf “select=’not(mod(n,${probeResponse.fps}))’,setpts=’N/(${probeResponse.fps}*TB)'”`
    } else {
    // fps=1/60 is 1 per min, fps=1/120 is 1 every 2 mins
    // results in thumbs which do not marry with the first frame of each second – TODO: Would rounding fps using the preferred approach work better?
    vf = ‘-vf fps=1/1’
    const rawThumbsCmd = `ffmpeg -i “${inFile}” -v warning -f image2 -bt 20M -aspect ${probeResponse.strAspectRatio} ${vf} “${outPath}/raw%0${cpatConfig.PAD_START}d${cpatConfig.EXT}”`

Leave a Comment

Your email address will not be published. Required fields are marked *

Enjoying this article? Subscribe to OTTVerse and receive exclusive news and information from the OTT Industry.