I'm trying to capture high quality screen recording with the minimum CPU load (what we're recording is already CPU intensive and suffers slowdown if encoding is being done at the same time as screen recording).
I'm using this command:
ffmpeg -f gdigrab -t 00:00:05 -i desktop -pix_fmt yuv420p -vcodec copy -y testing.avi
When I open this in Windows Media Player or VLC it sort of works. It's the right size and duration, but the pixels are messed up, as shown below.
Ultimately I'd like to be able to re-encode this to something smaller, again using ffmpeg, but I can't find the right ffmpeg incantation/options for this given the raw input file generated by the first command.
The output codec of gdigrab
is BMP.
For grabbing with -codec copy
we have to store each frame in separate BMP image file.
Example:
ffmpeg -r 30 -f gdigrab -t 00:00:05 -i desktop -vcodec copy %08d.bmp
Later we can encode the images offline:
ffmpeg -r 30 -i %8d.bmp -vcodec libx264 -pix_fmt yuv420p -y testing.mp4
Using gdigrab
and BMP images is probably not the most efficient solution.
Modern CPUs that has an internal GPU support iGPU accelerated encoding.
Example for using Intel Quick Sync encoder:
ffmpeg -init_hw_device qsv=hw,child_device_type=dxva2 -filter_hw_device hw -f dshow -i video="screen-capture-recorder" -t 00:00:05 -vf "hwupload=extra_hw_frames=64,format=qsv" -c:v h264_qsv -b:v 5M -pix_fmt nv12 -y testing.mp4
It may not work if your system doesn't support Intel Quick Sync.
Note: I am getting an error message: "Impossible to convert between the formats supported by the filter" (I think it's an issue with my system configuration because QSV encoding is not working in general).
The following command is working in my machine (but 20% CPU utilized by FFmpeg):
ffmpeg -init_hw_device qsv=hw,child_device_type=dxva2 -filter_hw_device hw -f dshow -i video="screen-capture-recorder" -t 00:00:05 -c:v h264_qsv -b:v 5M -y testing.mp4
In case your system has discrete GPU, it may be possible to use the discrete GPU for encoding the video.
Intel and AMD names are QSV and AMF.
When GPU encoding is used, gdigrab
may not be the most efficient solution.
FFmpeg version 6 (not yet stable release) supports ddagrab for capturing the Windows Desktop.
The main advantage of ddagrab
over gdigrab
is that ddagrab
doesn't transfer the video frame from the GPU to the CPU (and also saves the pixel format conversions).
Example for using ddagrab
with NVIDIA GPU:
ffmpeg -f lavfi -i ddagrab -t 00:00:05 -c:v h264_nvenc -cq 18 -y output.mp4
Example for using ddagrab
with Intel Quick Sync:
ffmpeg -init_hw_device qsv=hw,child_device_type=dxva2 -filter_hw_device hw -f lavfi -i ddagrab -t 00:00:05 -c:v h264_qsv -b:v 5M -y testing.mp4
Note: I couldn't test the QSV solution yet.
When I use ffmpeg -f lavfi -i ddagrab -c:v h264_nvenc -cq 18 -y testing.mp4
, FFmpeg CPU utilization is around 0%
:
Note: The above command is working in my system because it has a discrete NVIDIA GPU.