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

  1. Capturing a single frame at a timestamp (runnable)
  2. Extracting one frame per second with fps
  3. Exporting every frame as an image sequence
  4. Choosing PNG vs JPG and controlling quality
  5. Resizing frames as you extract
  6. 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 frame
  • output.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
OptionMeaning
-ss 00:00:05Seek to 5 seconds before reading
-frames:v 1Output exactly one frame
-vf fps=1Sample one frame per second

Seeking before -i is 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 -ss is 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 (use fps=1/5 for one every 5 seconds, fps=2 for two per second)
  • output_%04d.png%04d becomes a zero-padded counter

The %04d sequence 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.

GoalFilterResult
Every frame(none)All frames as images
One per second-vf fps=11 image/sec
One every 5 seconds-vf fps=1/51 image/5 sec
Two per second-vf fps=22 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)
FormatSizeQualityBest for
PNGLargeLosslessEditing, archival, transparency
JPGSmallLossyPreviews, 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, -1 lets 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.



Tested with FFmpeg 8.1 — verified with our command-check script Primary sources: ffmpeg.org/ffmpeg.html / trac.ffmpeg.org/wiki/Seeking