Low-Latency High-Res Screen Capture with FFmpeg
Capturing high-resolution desktop video in real time using FFmpeg can easily lead to high latency, dropped frames, and system slowdowns if the pipeline is not properly tuned. This article outlines the essential configurations needed to achieve minimal latency, focusing on selecting the most efficient screen capture backends, offloading the encoding workload to dedicated hardware, adjusting internal buffer queues, and configuring encoder flags to eliminate frame buffering.
1. Use Direct Desktop Duplication Backends
The default desktop capture devices (like GDI on Windows or standard X11 capture on Linux) copy frames through the CPU, creating a severe bottleneck at 1440p or 4K resolutions. You must use modern, GPU-native capture APIs.
- Windows (DirectX Desktop Duplication API): Use
ddagrabinstead ofgdigrab. It captures frames directly from the GPU memory. - Linux: Use
kmsgrabfor direct capture from the kernel mode setting, or use an optimized PipeWire/Wayland screencast bridge. - macOS: Use
avfoundationwith capture options optimized for screen capture.
2. Offload Encoding to Hardware (GPU)
Software encoding (such as libx264) at high resolutions
consumes heavy CPU cycles and introduces encoding delay. Use
hardware-accelerated encoders:
- NVIDIA:
h264_nvencorhevc_nvenc - Intel:
h264_qsvorhevc_qsv - AMD:
h264_amforhevc_amf
Pair the hardware encoder with a low-latency preset to bypass
lookahead buffers. For example, with NVENC, use -preset p1
(fastest performance) or -tune zerolatency.
3. Eliminate FFmpeg Pipeline Buffers
FFmpeg by default analyzes incoming streams to determine parameters, which introduces capture delay. Disable this analysis and strip out frame buffering:
- Reduce Analysis Time: Set
-probesize 32and-analyzeduration 0before the input flag. - Prevent Frame Queue Dropping: Allocate a larger
thread queue size to the input using
-thread_queue_size 1024or higher so processing spikes do not cause frame drop warnings. - Remove B-Frames: B-frames require the encoder to
wait for future frames before finishing the current frame. Force zero
B-frames with
-bf 0. - Zero Latency Tuning: Pass
-tune zerolatencyto tell the encoder to output frames immediately upon arrival.
4. Optimize Container and Storage I/O
Writing uncompressed or poorly buffered data directly to a slow disk creates backpressure on the capture pipeline.
- Record to a fast NVMe drive or a RAM disk (
/dev/shmon Linux). - Use lightweight container formats like Matroska (
.mkv) or fragmented MP4 (-movflags frag_keyframe+empty_moov), which do not require keeping a complete index in memory while recording.
Production Example Commands
Windows (DirectX Desktop Duplication + NVIDIA NVENC):
ffmpeg -probesize 32 -analyzeduration 0 -thread_queue_size 1024 \
-f ddagrab -framerate 60 -i desktop \
-c:v h264_nvenc -preset p1 -tune zerolatency -bf 0 -rc cbr -b:v 20M \
-maxrate 20M -bufsize 5M -an output.mkvLinux (X11 Desktop + NVIDIA NVENC):
ffmpeg -probesize 32 -analyzeduration 0 -thread_queue_size 1024 \
-f x11grab -framerate 60 -video_size 2560x1440 -i :0.0 \
-c:v h264_nvenc -preset p1 -tune zerolatency -bf 0 -rc cbr -b:v 20M \
-maxrate 20M -bufsize 5M -an output.mkvBy pairing a direct GPU-level capture backend with hardware encoding and zero-latency stream flags, the total latency between pixel display and encoded disk output is kept down to a fraction of a single frame.