Pulling still images out of a video is one of FFmpeg’s most useful tricks — building a contact sheet, grabbing a single clean frame for a thumbnail, or exporting frames to feed into another tool. FFmpeg can export frames as PNG or JPG, either every frame, at a steady rate like one per second, or a single shot at an exact timestamp. This guide walks through each approach and the quality settings that matter. Estimated time: 7 minutes.
Tested with: FFmpeg 8.1
What You’ll Learn
- Capturing a single frame at a timestamp (runnable)
- Extracting one frame per second with
fps - Exporting every frame as an image sequence
- Choosing PNG vs JPG and controlling quality
- Resizing frames as you extract
- Troubleshooting and FAQ
1. Capture a Single Frame
The most common need is one good still. Use a filter to pick a frame and stop after the first one:
ffmpeg -i input.mp4 -vf fps=1 -frames:v 1 output.png
-vf fps=1… sample the stream at one frame per second-frames:v 1… write only the first matching frameoutput.png… a single PNG image
To grab a frame at a specific moment instead, seek before the input. This pulls the frame at the 5-second mark:
ffmpeg -ss 00:00:05 -i input.mp4 -frames:v 1 output.png
| Option | Meaning |
|---|---|
-ss 00:00:05 | Seek to 5 seconds before reading |
-frames:v 1 | Output exactly one frame |
-vf fps=1 | Sample one frame per second |
Seeking before
-iis fast, and in modern FFmpeg it’s also accurate when decoding/transcoding: FFmpeg jumps to a nearby keyframe, then decodes forward to land on the exact target frame by default. Output-side-ss(after-i) reaches the same frame but is slower because it decodes from the start, so input-side-ssis generally the better choice for frame extraction. See the Seeking wiki.
2. Extract One Frame per Second
To turn a video into a series of stills at a steady rate, sample with fps and write a numbered sequence:
ffmpeg -i input.mp4 -vf fps=1 output_%04d.png
This produces output_0001.png, output_0002.png, … one image for each second of the video.
-vf fps=1… one frame per second (usefps=1/5for one every 5 seconds,fps=2for two per second)output_%04d.png…%04dbecomes a zero-padded counter
The
%04dsequence is shown as plain text because the counter is filled in by FFmpeg at run time, not typed literally.
3. Export Every Frame
To dump every frame as an image (for frame-by-frame inspection or feeding another pipeline), omit any rate filter:
ffmpeg -i input.mp4 output_%04d.png
This writes one PNG per frame, so a 30 fps clip yields 30 images per second of video — that adds up fast, so make sure you have disk space.
| Goal | Filter | Result |
|---|---|---|
| Every frame | (none) | All frames as images |
| One per second | -vf fps=1 | 1 image/sec |
| One every 5 seconds | -vf fps=1/5 | 1 image/5 sec |
| Two per second | -vf fps=2 | 2 images/sec |
4. PNG vs JPG and Quality
PNG is lossless and ideal when you need pixel-perfect frames; JPG is much smaller and fine for previews. To export a JPG single frame and control its quality:
ffmpeg -ss 00:00:05 -i input.mp4 -frames:v 1 -q:v 2 output.jpg
-q:v 2… JPG quality (2 is high; the scale runs 2–31, lower is better)
| Format | Size | Quality | Best for |
|---|---|---|---|
| PNG | Large | Lossless | Editing, archival, transparency |
| JPG | Small | Lossy | Previews, contact sheets, web |
For a polished single-image thumbnail with smart frame selection, see the thumbnail guide.
5. Resize Frames While Extracting
Combine scale with the frame selection to export smaller images directly. This grabs a frame at 5 seconds and scales it to 640px wide (height auto-kept in proportion):
ffmpeg -ss 00:00:05 -i input.mp4 -vf scale=640:-1 -frames:v 1 output.png
scale=640:-1… set width to 640,-1lets FFmpeg compute the height to keep aspect ratio
You can chain filters; for example -vf "scale=640:-1,fps=1" resizes and samples at once.
6. Troubleshooting
Issue 1: Only one image is written when I wanted many
Cause: The output name lacked a %04d pattern, so each frame overwrote the same file.
Fix: Include %04d (or similar) in the output name for a sequence (section 2).
Issue 2: The extracted frame is slightly off the moment I wanted
Cause: When extracting frames (which decodes), input-side -ss is normally accurate in modern FFmpeg — it decodes to the exact target. A noticeable offset usually means an older FFmpeg build, a stream-copy path, or a damaged file.
Fix: Update FFmpeg, or as an alternative place -ss after -i (slower, decodes from the start):
ffmpeg -i input.mp4 -ss 00:00:05 -frames:v 1 output.png
Issue 3: PNG files are huge
Cause: PNG is lossless and uncompressed in detail.
Fix: Export JPG with -q:v for far smaller files (section 4).
FAQ
Q1. What’s the difference between extracting frames and making a thumbnail? A. Extracting frames gives you raw stills at a chosen rate; the thumbnail workflow adds smart selection and sizing for a single representative image.
Q2. How do I get one frame every N seconds?
A. Use -vf fps=1/N. For example fps=1/10 gives one frame every 10 seconds.
Q3. Can I extract frames as JPG instead of PNG?
A. Yes. Use a .jpg output name and -q:v 2 for high quality (section 4).
Q4. My image sequence overwrites itself — why?
A. Your output filename has no counter. Add %04d so each frame gets a unique number.
Q5. Does extracting frames affect the original video? A. No. FFmpeg only reads the input; the source file is never modified.
Related Articles
Tested with FFmpeg 8.1 — verified with our command-check script Primary sources: ffmpeg.org/ffmpeg.html / trac.ffmpeg.org/wiki/Seeking