How to Make a Contact Sheet with FFmpeg (And When You Shouldn't)
The actual FFmpeg command to build a video contact sheet with the thumbnail and tile filters, plus when a visual Mac workflow beats re-running the command.
Here is the FFmpeg contact sheet command: ffmpeg -i input.mp4 -vf "thumbnail,tile=4x4" -frames:v 1 sheet.png. That single pass samples representative frames and tiles them into one grid image. It works, and for scripted or server jobs it is the right tool.
The friction starts when the sheet has to be reviewed by a person. Picking better frames, labeling each one with a timecode, and fixing a cell that landed on a blink all mean editing flags and re-running. Sequence Pro keeps FFmpeg-style media handling under the hood and moves those decisions into a native macOS canvas: add a video, sample frames, tune weak moments, add timestamps and metadata, then export PNG or JPEG.
The FFmpeg contact sheet command, explained
The classic recipe combines two filters in one -vf chain. The thumbnail filter scores frames and picks the most representative one from each batch, and tile assembles those picks into a grid.
ffmpeg -i input.mp4 -vf "thumbnail,tile=4x4" -frames:v 1 sheet.png
thumbnailanalyzes frames in batches (100 by default) and selects one representative frame per batch.tile=4x4arranges the incoming frames into a 4-by-4 grid, so this sheet holds 16 cells.-frames:v 1tells FFmpeg to write a single output image instead of a sequence.
If you want even time-based coverage instead of FFmpeg’s automatic picks, swap thumbnail for an fps filter that grabs one frame every N seconds:
ffmpeg -i input.mp4 -vf "fps=1/10,scale=320:-1,tile=5x5" -frames:v 1 sheet.png
fps=1/10keeps one frame every 10 seconds of source.scale=320:-1resizes each thumbnail to 320px wide, preserving aspect ratio.tile=5x5builds a 25-cell grid in a single image.
- thumbnail filter
- Selects the most representative frame from each batch of frames, useful for avoiding obvious throwaway frames automatically.
- tile filter
- Assembles incoming frames into a single image grid using a columns-by-rows geometry such as 4x4 or 5x5.
- fps filter
- Forces a fixed sampling rate, such as fps=1/10 for one frame every ten seconds, to drive even time-based coverage.
Micro-FAQ
- What does
-frames:v 1do? It limits output to a single video frame, which is the assembled grid image rather than a stream of tiles. - How do I get more cells? Increase the
tilegeometry (for exampletile=6x6) and feed it enough frames viathumbnailorfps. - Does this make a contact sheet image, not a movie? Yes. With a
.pngor.jpgoutput and-frames:v 1, FFmpeg writes one composed image.
Where the FFmpeg contact sheet command starts costing time
The command is easy to run once and tedious to iterate. A contact sheet is a review artifact, and review work needs judgment that flags cannot encode.
The cost shows up after the first sheet renders:
- No preview loop. You run the command, open the file, and only then learn whether the grid tells the story. Adjusting means editing flags and re-running.
- Timestamp labeling is fiddly. Burning per-cell timecode means adding
drawtextbeforetile, so each frame is labeled before it is assembled. - Font and escaping overhead.
drawtextoften needs an explicitfontfile, plus careful escaping of theptsexpansion and manualx/ypositioning. - Bad frames are sticky. If a cell lands on a cut, blink, fade, or motion blur, there is no swap-this-one control. You change sampling and regenerate the whole sheet.
- Context lives elsewhere. Source name, duration, resolution, and codec usually end up in a separate note instead of on the sheet.
A burned-in timecode chain looks like this, and the ordering and escaping are exactly where it gets brittle:
ffmpeg -i input.mp4 -vf "fps=1/10,drawtext=fontfile=/Library/Fonts/Arial.ttf:text='%{pts\:hms}':fontcolor=white:fontsize=24:x=10:y=10,scale=320:-1,tile=5x5" -frames:v 1 sheet.png
That is a lot of syntax to maintain every time the source, layout, or label needs to change. This is why make contact sheet from video ffmpeg searches so often turn into a workflow question, not a syntax question.
(Placeholder: Screenshot of a terminal showing the FFmpeg tile command beside its rendered grid output.)
The visual workflow on Mac
Sequence Pro keeps the FFmpeg-powered media reads and moves the contact sheet decisions into a canvas you can see. Instead of editing a filter chain and re-running, you work against a live preview and export when the selected sheet is right.
Quick stat block
- Platform: native macOS workflow for Apple Silicon and Intel Macs.
- Media tooling: bundled FFmpeg/FFprobe in release workflows.
- Performance: optional VideoToolbox hardware acceleration where supported.
- Output: high-fidelity PNG/JPEG contact sheet and frame-reference exports.
Step 1: Add a video instead of writing an input flag
Start from the source file, not a command template. Drag a local video into Sequence Pro and select it in the queue so the app can read it for preview and frame extraction.
For local files this supports local offline processing after activation, which matters for client media, unreleased clips, and archive references that should stay on your Mac.
(Placeholder: Screenshot of the Sequence Pro queue with a selected local video and preview canvas.)
Step 2: Choose frame sampling visually
Frame sampling is the UI version of the thumbnail or fps decision. Pick a fixed count when you want a predictable grid, or interval-style sampling when the source duration should drive coverage.
Use a fixed count such as 12, 16, or 24 frames for a classic contact sheet. Use interval-style sampling for long interviews, gameplay captures, inspection clips, and lectures where more runtime needs more moments.
(Placeholder: Screenshot of frame sampling controls showing fixed count and interval-style choices.)
Step 3: Tune the weak frames before export
This is the step the command line cannot do well. A sampled frame can be technically valid and still be the wrong frame for review: a blink, a fade, a motion smear, or a near-duplicate.
Sequence Pro lets you swap weak cells individually instead of regenerating the whole grid. You get automation where it saves time and editorial judgment where it protects quality.
(Placeholder: Screenshot of frame tuning with one sampled cell selected for adjustment.)
Stop re-running a filter chain to fix one bad cell. Try Sequence Pro when your contact sheet needs visual review before export.
Step 4: Add timestamps and metadata tokens
Burned-in timing is a checkbox here, not a drawtext chain. Timestamps make each frame traceable to its source moment, and metadata tokens add sheet-level context without a separate document.
Useful token patterns include:
- Source name:
{stem}or{display_name} - Runtime:
{duration_hms} - Technical details:
{resolution},{fps}, and{codec} - Export context:
{date}and{time} - Custom metadata:
{meta.<key>}for archive or project fields
Keep labels short so they clarify the grid rather than compete with it.
(Placeholder: Screenshot of a contact sheet with timestamps on frames and a metadata text layer.)
Micro-FAQ
- Can Sequence Pro burn timecode onto each frame? Yes. Timestamp styling adds per-frame timing without managing
drawtextsyntax. - Can I add source metadata? Yes, via tokens such as
{stem},{resolution},{duration_hms},{fps},{codec}, and{display_name}. - Does this create a new movie file? No. Sequence Pro exports composed image files from sampled frames.
Step 5: Export PNG or JPEG from the selected video
The deliverable is one image people can use immediately. Once the selected video’s sheet is readable, export it as PNG or JPEG.
Use PNG when text clarity, crisp timestamps, or maximum fidelity matters. Use JPEG when smaller files are better for email, chat, tickets, or lightweight documentation.
The workflow stays selection-based: add one or more videos, select the one you want to compose, sample and preview the sheet, add timestamps or metadata, then export that selected video’s current sheet.
(Placeholder: Screenshot of export controls showing PNG/JPEG options and a finished contact sheet.)
When the raw FFmpeg command is still the right tool
Keep the command line when the job is genuinely command-shaped. Sequence Pro is deliberately focused on frame extraction, timestamps, contact sheets, and canvas image export, not every operation FFmpeg can perform.
Use the raw tile command for:
- Server automation and scheduled scripts where no human reviews each sheet.
- Bulk jobs that fan a fixed recipe across many files at once.
- Codec conversion and delivery ladders unrelated to visual indexing.
- Complex filter graphs that go beyond a contact sheet.
- Audio-only processing and other non-image workflows.
Use Sequence Pro when the output needs human judgment: you want to see the frames, tune the weak moments, add source context, and export a polished visual index.
FAQ
What is the FFmpeg command for a contact sheet?
Combine the thumbnail and tile filters in one pass, for example ffmpeg -i input.mp4 -vf "thumbnail,tile=4x4" -frames:v 1 sheet.png. The thumbnail filter picks representative frames and tile arranges them into a single grid image.
How do I control how many frames are on the FFmpeg contact sheet?
The tile geometry sets the grid. tile=4x4 produces 16 cells and tile=5x5 produces 25. Pair tile with fps=1/N (one frame every N seconds) or the thumbnail filter to control which frames fill those cells.
Can FFmpeg add timestamps to each frame on the contact sheet?
Yes, with the drawtext filter using a pts expansion such as %{pts:hms}, but drawtext must run before tile so each cell is labeled, and you have to manage font paths, escaping, and positioning manually.
When should I use a GUI instead of the FFmpeg command?
Use a GUI like Sequence Pro when the sheet needs visual review, frame swaps, readable timestamps, source metadata, and a polished image to send, rather than re-running a command until the grid looks right.
Final word
The FFmpeg contact sheet command is excellent at extraction and weak at review. It will build a grid in one pass, but it cannot judge whether the grid is readable, swap a bad cell, or label timing without a brittle drawtext chain.
Sequence Pro wraps that specific job in a native macOS workflow: local video in, tuned and timestamped contact sheet out, with canvas-based PNG or JPEG export.
Get Sequence Pro on Gumroad - one-time license, no subscription, with all 1.x updates included. Try it free when you want FFmpeg-powered contact sheets without maintaining terminal commands.