Official ffmpeg documentation on this: Create a thumbnail image every X seconds of the video
Output one image every second:
ffmpeg -i input.mp4 -vf fps=1 out%d.png
Output one image every minute:
ffmpeg -i test.mp4 -vf fps=1/60 thumb%04d.png
Output one image every 10 minutes:
ffmpeg -i test.mp4 -vf fps=1/600 thumb%04d.png
Answer from Vitaliy Fedorchenko on Stack OverflowOfficial ffmpeg documentation on this: Create a thumbnail image every X seconds of the video
Output one image every second:
ffmpeg -i input.mp4 -vf fps=1 out%d.png
Output one image every minute:
ffmpeg -i test.mp4 -vf fps=1/60 thumb%04d.png
Output one image every 10 minutes:
ffmpeg -i test.mp4 -vf fps=1/600 thumb%04d.png
You can use the select filter for a set of custom ranges:
ffmpeg -i in.mp4 -vf select='between(t,2,6)+between(t,15,24)' -vsync 0 out%d.png
Can I extract frames as JPG instead of PNG?
Does extracting frames affect the original video?
What's the difference between extracting frames and making a thumbnail?
I made an image sequence of 100 png files from a H.265 video, and now I want to make a H.264 video out of those frames without losing quality. How do I do that?
I was wonder how I can use ffmpeg to extract all the frames from a video losslessly(at least visually) and then recombine them back without losing quality?
Just mux the images
You can simply mux the JPG images to make a video:
ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv
Note that if you omit -framerate then a default of -framerate 25 will be applied to the input.
Lossless optimization
You can use jpegtran to perform lossless optimization on each frame which may provide significant file size savings:
mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done
Now mux with ffmpeg as shown above.
Checking that it is actually lossless
The framehash muxer can be used to compare the unique hash of each frame to ensure that the result is truly lossless:
$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
In the above examples each associated frame for the input and output share the same hash ensuring that the frames are identical and that the output is lossless.
Also see
- FFmpeg image file demuxer documentation
- FFmpeg Wiki: How do I encode single pictures into movies?
This will output a lossless H.264 video where frames will use information from other frames
ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4
Explanation of options:
-f image2- tells ffmpeg to select a group of images-r 30- tells ffmpeg to encode at 30 frames (or images) per second (change this to your desired framerate)-i %09d.jpg- tells ffmpeg to use the images 000000000.jpg to 999999999.jpg as the input. Change the9in%09d.jpgto how many zeroes the names of your image sequence has. If your file names are, for example, img0001.jpg, then this would be expressed as img%04d.jpg-vcodec libx264- tells ffmpeg to output to a H.264 compliant file-profile:v high444- tells libx264 to use the High 4:4:4 Predictive Lossless profile, allowing lossless encoding-refs 16- tells libx264 to have 16 images stored in a buffer, so that they may be referenced by other images in the video-crf 0- tells libx264 to perform a lossless encode-preset ultrafast- tells libx264 to prioritise encoding speed over output file sizea.mp4- tells ffmpeg to save the output in an MP4 file called a.mp4. Change this to the file name and format that you wish to use
Use -qscale:v to control quality
Use -qscale:v (or the alias -q:v) as an output option.
- Normal range for JPEG is 2-31 with 31 being the worst quality.
- The scale is linear with double the qscale being roughly half the bitrate.
- Recommend trying values of 2-5.
- You can use a value of 1 but you must add the
-qmin 1output option (because the default is-qmin 2).
To output a series of images:
ffmpeg -i input.mp4 -qscale:v 2 output_%03d.jpg
See the image muxer documentation for more options involving image outputs.
To output a single image at ~60 seconds duration:
ffmpeg -ss 60 -i input.mp4 -qscale:v 4 -frames:v 1 output.jpg
To continuously overwrite/update/save to a single image
Use -update 1 image muxer option. Example for once per second from a live streaming input:
ffmpeg -i rtmp://input.foo -q:v 4 -r 1 -update 1 output.jpg
Also see
- FFmpeg FAQ: How do I encode movie to single pictures?
- FFmpeg Wiki: Create a thumbnail image every X seconds of the video
Output the images in a lossless format such as PNG:
mkdir stills
ffmpeg -i my-film.mp4 -vsync 0 -f image2 stills/my-film-%06d.png
Then use another program (where you can more precisely specify quality, subsampling and DCT method – e.g. GIMP) to convert the PNGs you want to JPEG.
It is possible to obtain slightly sharper images in JPEG format this way than is possible with -qmin 1 -q:v 1 and outputting as JPEG directly from ffmpeg.
If you want to extract only the key frames (which are likely to be of higher quality post-edit) you can use something like this:
ffmpeg -skip_frame nokey -i my-film.mp4 -vsync 0 -f image2 stills/my-film-%06d.png
The -vsync 0 parameter avoids needing to specify the frame rate with -r and means all frames in the input file are treated as, um, a frame.