Automatically generate video thumbnails using ffmpeg and bash
Table of Contents
- Automatically extracting frames as a thumbnail
- Using the thumbnail filter
- Attaching your chosen thumbnail to the video
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.
#!/bin/bash echo "Working on file: $1" let numframes=$( ffprobe -v error \ -select_streams v:0 \ -count_packets \ -show_entries stream=nb_read_packets \ -of csv=p=0 $1) echo "Total number of frames : $numframes" let offset=(numframes/10) for ((i=1; i<=10; i++)) do let extractframe=($offset*$i) echo "Extracting frame : $extractframe" ffmpeg -i $1 \ -nostats \ -loglevel 0 \ -vf "select=eq(n\,$extractframe)" \ -vframes 1 \ poster_$extractframe.png done
↑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:
ffmpeg -i input.mp4 \ -vf "thumbnail=300" \ -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
ffmpeg -i input.mp4 \ -i thumbnail.png \ -map 1 \ -map 0 \ -c copy \ -disposition:0 attached_pic output.mp4