Automatically generate video thumbnails using ffmpeg and bash

Written by Paul Bradley

midjourney ai - first human alien contact

Table of Contents
  1. Introduction
  2. Automatically extracting frames as a thumbnail
  3. Using the thumbnail filter
  4. Attaching your chosen thumbnail to the video

Introduction

Following on from my HLS video streaming post, I wanted to explore different ways of automatically generating thumbnail images that can could be used as the poster attribute of the video tag.

In this article we’ll create a bash script that will extract a frame at every 10% point between ten and ninety percent. This will give us nine images to choose from.

We’ll also look at using ffmpeg’s thumbnail filter, which attempts to select the most significant frame/image from the video.

Finally, we’ll look at how to attach our chosen image back into the video, setting it as the video’s thumbnail.

Automatically extracting frames as a thumbnail

Below is bash script which takes the input video filename as the first argument. It uses the ffprobe command to calculate the total number of frames within the supplied video file. The total number of frames is returned from the ffprobe command and assigned to the variable numframes.

We then define a new variable called offset which is the value of the number of frames divided by ten.

We then go into a loop and extract the frame at the position offset. The value of offset is increased each time around the loop.

 1#!/bin/bash
 2echo "Working on file: $1"
 3
 4let numframes=$(
 5    ffprobe -v error \
 6    -select_streams v:0 \
 7    -count_packets \
 8    -show_entries stream=nb_read_packets \
 9    -of csv=p=0 $1)
10
11echo "Total number of frames : $numframes"
12let offset=(numframes/10)
13
14for ((i=1; i<=10; i++))
15do
16    let extractframe=($offset*$i)
17    echo "Extracting frame : $extractframe"
18
19    ffmpeg -i $1 \
20        -nostats \
21        -loglevel 0 \
22        -vf "select=eq(n\,$extractframe)" \
23        -vframes 1 \
24        poster_$extractframe.png
25done

Using the thumbnail filter

ffmpeg has lots of built-in filters to help you manipulate your media files. One of them is the thumbnail filter. It will select the most representative frame in a given sequence of consecutive frames automatically from the video.

To use the thumbnail filter, add -vf “thumbnail” to the basic command:

1ffmpeg -i input.mp4 \
2       -vf "thumbnail=300" \
3       -frames:v 1 thumbnail-300.png

ffmpeg analyzes the frames in batches of 300 and picks the most representative frame out of them. The process continues until the end of the video and we get the best frame among all the batches.

Attaching your chosen thumbnail to the video

1ffmpeg -i input.mp4 \
2       -i thumbnail.png \
3       -map 1 \
4       -map 0 \
5       -c copy \
6       -disposition:0 attached_pic output.mp4