FFmpeg: How to take screenshots

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.

More FFmpeg commands

asterix Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *