FFmpeg extract frames from video: one, every second, or all
Extract frames with FFmpeg: -frames:v 1 saves one image, -r 1 saves one per second, and a numbered file pattern writes every frame.

To extract frames from a video with FFmpeg, give it an image file as the output: -frames:v 1 stops after one frame, -ss picks where it's taken, -r 1 writes one frame per second, and a numbered pattern such as frame-%04d.png holds a whole sequence. FFmpeg's own example, ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg, extracts one frame per second and rescales each to WxH.
The FFmpeg facts come from its ffmpeg, filters, and formats documentation, and the Sume facts from the Video frames docs, all read on 2026-09-28.
How do I extract a single frame?
Stop after one frame, and seek first if you don't want the start:
-frames:v 1stops writing after one frame; FFmpeg's image muxer docs use it to make a single image from the start of a video.-ssbefore-iseeks the input. Writing an image means decoding, and with-accurate_seek, the default, FFmpeg decodes and discards the stretch between the nearest seek point and your position, so you get the frame at the time you asked for.-sseof -1seeks one second before the end, and-update 1overwrites the same file with each new image, so the file ends up holding the last frame. Extract the last frame of a video does the same with the Sume API.- With an image extension such as
.pngand no-f, FFmpeg picks its image2 muxer automatically.
# The first frame
ffmpeg -i input.mp4 -frames:v 1 first.png
# The frame at 5 seconds
ffmpeg -ss 5 -i input.mp4 -frames:v 1 frame.png
# The last frame
ffmpeg -sseof -1 -i input.mp4 -update 1 last.pngHow do I extract a frame every second, or every Nth frame?
Set an output rate, or select frames with a filter. With select, add -fps_mode vfr, which FFmpeg's docs say passes frames through with their timestamps; in cfr mode, frames are duplicated and dropped to hold a constant rate:
| To get | FFmpeg option | What FFmpeg's docs say |
|---|---|---|
| One frame | -frames:v 1 | Stop writing to the stream after that many frames |
| One frame per second | -r 1, or -vf fps=1 | Both duplicate or drop frames to reach a constant output rate |
| Every 100th frame | -vf select='not(mod(n\,100))' | Select one frame every 100 |
| Keyframes only | -vf select='eq(pict_type\,I)' | Select only I-frames |
| One representative frame | -vf thumbnail -frames:v 1 | Picks the most representative frame of each batch of frames, 100 by default, so this keeps the first batch's pick |
| Every frame | -fps_mode passthrough | Each frame is passed with its timestamp from the demuxer to the muxer |
# One frame per second
ffmpeg -i input.mp4 -r 1 frame-%03d.jpeg
# Every 100th frame
ffmpeg -i input.mp4 -vf "select='not(mod(n\,100))'" -fps_mode vfr frame-%03d.pngHow do I export every frame as an image sequence?
Pass every decoded frame straight through to a numbered file pattern:
%05dpads each number to five digits. The first file is number 1 unless you set-start_number.- Count before you run it: by our arithmetic, a 60-second clip at 30 fps is 1,800 images.
- PNG keeps every pixel; JPEG files are smaller but lossy.
-s WxHrescales the images, as in FFmpeg's own example.
ffmpeg -i input.mp4 -fps_mode passthrough frame-%05d.pngCan I extract frames with the Sume API?
Yes, as individual stills, not as a full sequence. POST /v1/video-frames returns at most 24 durable stills per call, at times you list in at[] or sampled with fps up to 2, from sources of up to 300 seconds, and the call is unbilled. Exporting every frame stays an FFmpeg job. How to extract frames with the Sume API covers the request, its fields, and its refusals.
- Its
fpssamples mid-bin:fps: 1takes stills at 0.5 s, 1.5 s, and so on, where FFmpeg's-r 1writes one frame per second of video. video_urlmust be your workspace'smedia.sume.comartifact or asset, such as an earlier Sume job's output; which URLs each endpoint accepts explains the rule.
Sources
Related posts
More in Developers
- FFmpeg height not divisible by 2: why and how to fix it
The error means a yuv420p encode got an odd height (or width). Make both even: scale with -2 or round with trunc(ih/2)*2. How Sume rounds sizes.
- FFmpeg merge audio and video: -map, copy, and -shortest
Merge audio and video with FFmpeg: map the video from one file and the audio from the other, copy the video, and add -shortest to match lengths.
- FFmpeg trim video: cut by time, with or without re-encoding
Trim a video with FFmpeg: -ss before -i to seek, -t for the length, and -c copy to skip re-encoding, which starts the cut at the keyframe before.
- Higgsfield API key: how to get one and send it
A Higgsfield API key is a key ID plus a secret made in Higgsfield Console, sent together in one Authorization: Key header from server code only.
Written by Sume