FFmpeg is a powerful command-line tool that can be used for video and audio processing, including taking screenshots from video files. There are several options to take screenshots, either with a set time or specific frame.
Screenshot at a specific time
ffmpeg -ss 00:00:10 -i input.mkv -frames:v 1 screenshot.png
-ss 00:00:10
the timestamp at which the screenshot should be taken. In this example, we’re taking a screenshot at the 10th second of the video [hours:minutes:seconds].
-i input.mkv
specifies the input file.
-frames:v 1
determines the number of frames to output. In this case, one frame will be saved as a screenshot.
screenshot.png
defines the output file name and format. This can be changed to any file name and format.
Screenshot at a specific frame number
ffmpeg -i input.mkv -vf "select=eq(n\,100)" -frames:v 1 screenshot.png
-vf "select=eq(n\,100)"
this option applies a video filter vf
to the input file. In this example, the select
filter is used to choose the frame at the specified frame number. The expression eq(n\,200)
selects the frame at index 200.
Screenshots at every second
ffmpeg -i input.mkv -r 1 screenshot_%02d.png
-r 1
sets the output frame rate. In this case, we set it to 1, which means one frame per second. One frame every two seconds would be r 0.5
and two frames every second would be r 2
.
screenshot_%02d.png
this command adds an auto generated two-digit number to each screenshot.
Screenshot every frame for a given time period
ffmpeg -ss 00:00:10 -t 2 -i input.mkv screenshot_%02d.png
-t 2
sets the duration of the capture to 2 seconds. Between 00:00:10 and 00:00:12 every single frame will be captured as screenshot.
Screenshot of HDR10 video and tone map output to SDR
Screenshots taken with FFmpeg from HDR video may look washed out because of the difference between the HDR and SDR color spaces. HDR video uses a wider color gamut and a higher dynamic range than SDR video, so when you take a screenshot of an HDR video and display it on an SDR display, the colors may look washed out.
To avoid this issue, you should tone map the HDR video to SDR. This can be done with the tonemap
filter in FFmpeg to apply a tone mapping algorithm to the HDR video and convert it to SDR. As a result, screenshots will have accurate colors and contrast when displayed on an SDR device.
The following comment is from GitHub and is pretty accurate in tone for the colors:
ffmpeg -ss 00:00:10 -t 2 -i inputK.mkv -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p screenshot_%02d.png
Let’s break down the video filter into its parts:
zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv
tin=smpte2084
sets the transfer characteristics of the input color space to SMPTE ST 2084 (PQ) transfer function. This is the transfer function used in HDR video.
min=bt2020nc
sets the minimum luminance value of the input to BT.2020 non-constant luminance. This is the minimum luminance value used in HDR video.
pin=bt2020
sets the color primaries of the input to BT.2020 primaries. These are the color primaries used in HDR video.
rin=tv
sets the gamma correction curve of the input to the TV gamma curve. This is the gamma curve used in SDR video.
t=smpte2084
sets the transfer characteristics of the output color space to SMPTE ST 2084 (PQ) transfer function. This is the transfer function used in HDR video.
m=bt2020nc
sets the minimum luminance value of the output to BT.2020 non-constant luminance. This is the minimum luminance value used in HDR video.
p=bt2020
sets the color primaries of the output to BT.2020 primaries. These are the color primaries used in HDR video.
r=tv
sets the gamma correction curve of the output to the TV gamma curve. This is the gamma curve used in SDR video.
zscale=t=linear:npl=100
t=linear
specifies that the transfer function of the output video should be linear.
npl=100
sets a nominal peak luminance of 100 nits.
format=gbrpf32le
gbrpf32le
specifies a pixel format that represents video frames with 32 bits per pixel in planar format, where each pixel component (red, green, blue) is stored in a separate plane. The “le” at the end indicates that the byte order is little-endian.
zscale=p=bt709
p=bt709
is telling FFmpeg to convert the pixel format of the video frames to the bt709 color space which is used for standard dynamic range (SDR).
tonemap=tonemap=hable:desat=0
tonemap=hable
applies the Hable tone mapping algorithm to convert the HDR image to an SDR image.
desat=0
the desat parameter is set to 0 to avoid desaturating the colors.
zscale=t=bt709:m=bt709:r=tv
t=bt709
is a transfer function that is used for standard dynamic range (SDR) video. It is commonly used in HDTV and Blu-ray Discs, and is designed to provide a good balance of brightness and contrast for typical viewing conditions.
m=bt709
specifies the matrix coefficients that should be used for the output. Matrix coefficients define how the color components of the video signal (red, green, and blue) are weighted and combined to produce the final image. In this case the matrix coefficients used should be the same as those used in the bt709 color space.
r=tv
specifies the color range that should be used for the output. It indicates that the output color range should be limited to the range used for television broadcasting. This means that the brightest white value will be 235 instead of the full 255, and the blackest black value will be 16 instead of 0.
format=yuv420p
yuv420p
sets the pixel format to YUV 4:2:0, that converts to 8-bit.
Be First to Comment