Create a Video Contact Sheet with FFmpeg Tile Filter
This guide explains how to use the FFmpeg tile video
filter to generate a contact sheet or image grid from video frames. By
combining the tile filter with frame extraction filters
like fps or select, and optional scaling, you
can quickly produce thumbnail galleries summarizing an entire video into
a single image.
Basic Tile Filter Command
The tile filter takes sequential video frames and
arranges them into a grid defined as ColumnsxRows. Because
a standard video contains thousands of frames, you must downsample the
frame rate before tiling so the resulting sheet covers the desired
duration of the video.
The standard command structure is:
ffmpeg -i input.mp4 -vf "fps=1/60,scale=320:-1,tile=4x4" -frames:v 1 contact_sheet.pngBreakdown of the Parameters
-i input.mp4: Specifies the input video file.-vf: Defines the video filtergraph containing a chain of three operations:fps=1/60: Samples one frame every 60 seconds. Adjust this interval based on your video length and desired coverage.scale=320:-1: Resizes each extracted thumbnail to a width of 320 pixels while preserving the original aspect ratio (-1). Scaling down is critical to keep memory usage low and output dimensions manageable.tile=4x4: Arranges the thumbnails into a grid of 4 columns and 4 rows (16 frames total).
-frames:v 1: Tells FFmpeg to stop processing after outputting one single image frame.contact_sheet.png: The destination image file.
Adding Margins, Padding, and Colors
You can customize the layout of the contact sheet by adding borders between images and setting a background color:
ffmpeg -i input.mp4 -vf "fps=1/30,scale=300:-1,tile=3x3:nb_frames=9:padding=10:margin=20:color=white" -frames:v 1 contact_sheet.jpgnb_frames=9: Explicitly tells the tile filter to finish the grid after rendering 9 frames, ensuring it stops even if the video ends early.padding=10: Inserts a 10-pixel gap between each thumbnail.margin=20: Inserts a 20-pixel outer border around the entire grid.color=white: Sets the background, margin, and padding color (accepts color names or hex codes like0x000000).
Generating a Contact Sheet for a Specific Video Duration
If you want an evenly spaced contact sheet regardless of the file
length, calculate the fps value based on total video
duration:
\[\text{fps} = \frac{\text{Total Frames Needed}}{\text{Video Duration in Seconds}}\]
For example, to fit 25 frames (5x5 grid) across a
500-second video:
ffmpeg -i input.mp4 -vf "fps=25/500,scale=320:-1,tile=5x5" -frames:v 1 output.png