Troubleshooting FFmpeg Memory Leaks in Live Streams

Long-running FFmpeg processes used for 24/7 live streaming can occasionally suffer from unbounded memory growth, leading to system crashes or killed processes. This guide provides a direct, step-by-step approach to diagnosing and resolving memory leaks in FFmpeg, covering differentiation between true leaks and buffer accumulation, configuration tuning, filtergraph analysis, and native profiling tools.

1. Differentiate True Leaks from Buffer Accumulation

Before debugging C-level memory leaks, determine if FFmpeg is simply caching frames due to network latency, mismatched timestamps, or internal queue buildup.

  • Check Audio/Video Sync Drift: If the audio and video timestamps diverge, FFmpeg buffers packets in memory while waiting to interleave them properly. Look for warnings like Past duration ... too large or Non-monotonic DTS in your logs.
  • Inspect Protocol Buffers: In protocols like RTMP, SRT, or UDP, network congestion can cause output buffers to back up into system RAM.
  • Monitor Resident Set Size (RSS): Track RSS using ps -o rss,vsz -p <PID> over hours. An unbounded, linear climb that never plateaus indicates either a memory leak or an unconstrained queue.

2. Tune FFmpeg Command-Line Options

Misconfigured demuxers, muxers, and thread counts are the most frequent causes of runaway memory usage in continuous streams.

Constrain Muxing Queues

By default, recent versions of FFmpeg allocate a large muxing queue to prevent dropped frames. In unstable streams, this queue grows indefinitely. Cap it explicitly:

-max_muxing_queue_size 1024

Eliminate Frame Queuing

For live network inputs (RTSP, RTMP, WebRTC), minimize internal buffering with:

-fflags +nobuffer -flags low_delay

Limit Thread Allocations

Auto-threading (-threads 0) can allocate excessive frame buffers, especially when running software encoders like libx264 alongside complex filter pipelines. Explicitly set thread counts:

-threads 4 -filter_threads 2

3. Audit Complex Filtergraphs

Complex filter chains (such as overlay, concat, interlace, or fps) store frames in memory queues until all inputs have matching timestamps.

  • Fix Overlay Mismatches: If using -filter_complex overlay, ensure both input streams share identical, synchronized framerates. If one stream stops or stutters, the overlay filter buffers the other indefinitely. Use shortest=1 or configure fps filters on all inputs prior to merging.
  • Check Memory Usage Without Filters: Temporarily route raw input directly to the encoder using -c:v copy -c:a copy to test if the filtergraph is responsible for the memory increase.

4. Identify Buggy Third-Party Libraries

FFmpeg delegates encoding, decoding, and networking to external libraries. Memory leaks rarely originate in the FFmpeg core; they are commonly found in hardware acceleration drivers or external dependencies.

  • Hardware Encoders (NVENC, QSV, VAAPI): Outdated GPU drivers or memory leaks in vendor SDKs often cause system or VRAM exhaustion. Update your graphics drivers to the latest stable release.
  • External Codecs: Libraries like libvpx, libaom, and libass frequently release patches for memory leaks. Compile FFmpeg against the newest stable releases of these external libraries rather than relying on stale distribution packages.

5. Profile with Memory Analysis Tools

If configuration changes do not stop memory growth, capture the allocation trace using native diagnostic tools.

AddressSanitizer (ASan)

Compile a debug build of FFmpeg with ASan enabled. This introduces minimal overhead compared to Valgrind and can run against a real live stream:

./configure --enable-debug=3 --disable-optimizations --extra-cflags="-fsanitize=address" --extra-ldflags="-fsanitize=address"
make -j$(nproc)

Run your stream. Upon stopping the process or when memory spikes occur, ASan prints a detailed stack trace showing leaked memory blocks.

Valgrind Massif

To inspect high-water mark memory consumption over time, use the Massif tool:

valgrind --tool=massif --pages-as-heap=yes ffmpeg [your-stream-arguments]

Analyze the resulting massif.out.<pid> file with ms_print to see exact function calls that failed to deallocate memory.

6. Implement Production Safeguards

When debugging production environments where stream interruption must be mitigated immediately:

  • Enforce Memory Limits: Wrap the FFmpeg process in a systemd unit file with MemoryMax= or run inside a Docker container with --memory.
  • Graceful Handoffs: Use an orchestration script or process manager to spin up a parallel instance and switch RTMP/SRT output targets seamlessly every 24 to 48 hours to clear process memory.