Parse FFmpeg Progress Log Output to a File

Tracking the progress of an FFmpeg encoding task is essential for building responsive user interfaces, automating workflows, and calculating accurate completion percentages. FFmpeg natively supports streaming machine-readable metrics directly to a file using the -progress flag. This article explains how to write real-time progress data to a local file, understand the generated key-value metrics, and parse that file using a lightweight Python script.


Step 1: Directing FFmpeg Progress to a Local File

To output progress to a file instead of stderr, append the -progress flag followed by the target file path. Add the -nostats flag to suppress the default terminal output to keep the console clean.

ffmpeg -i input.mp4 -progress progress.log -nostats output.mp4

FFmpeg will continuously append blocks of key-value pairs to progress.log. Each update block looks like this:

frame=142
fps=35.50
stream_0_0_q=29.0
bitrate=   8.2kbits/s
total_size=48
out_time_us=4733333
out_time_ms=4733333
out_time=00:00:04.733333
dup_frames=0
drop_frames=0
speed=1.18x
progress=continue

Every block terminates with either progress=continue during processing or progress=end when the operation completes.


Step 2: Key Metrics to Track

The most useful keys generated in the output include:

  • out_time_us: Processed time in microseconds. Divide by 1,000,000 to get processed seconds. This is the most reliable metric for calculating completion percentage.
  • frame: Total number of video frames encoded so far.
  • fps: Current encoding speed in frames per second.
  • speed: Encoding speed relative to playback speed (e.g., 2.0x means twice as fast as real-time).
  • progress: Emits continue while running and end when finished.

Step 3: Parsing the Progress File in Python

Because FFmpeg continuously appends to the log, your parser needs to read the file sequentially or monitor it until progress=end is encountered.

Below is a Python script that reads the file line-by-line, groups lines into a key-value dictionary, and calculates the overall percentage against a known total duration:

import time
import os

def parse_ffmpeg_progress(file_path, total_duration_seconds):
    current_data = {}
    
    # Wait for the file to be created
    while not os.path.exists(file_path):
        time.sleep(0.1)

    with open(file_path, "r") as f:
        while True:
            line = f.readline()
            if not line:
                time.sleep(0.1)
                continue
            
            line = line.strip()
            if "=" in line:
                key, value = line.split("=", 1)
                current_data[key.strip()] = value.strip()

            # Process the current block when a progress state is reached
            if line.startswith("progress="):
                state = current_data.get("progress")
                
                if "out_time_us" in current_data:
                    current_us = int(current_data["out_time_us"])
                    current_seconds = current_us / 1_000_000
                    percentage = (current_seconds / total_duration_seconds) * 100
                    
                    print(f"Status: {percentage:.2f}% | "
                          f"FPS: {current_data.get('fps', 'N/A')} | "
                          f"Speed: {current_data.get('speed', 'N/A')}")
                
                if state == "end":
                    print("Processing complete.")
                    break
                
                # Clear buffer for next update block
                current_data.clear()

# Example usage (Total duration in seconds: 120)
parse_ffmpeg_progress("progress.log", total_duration_seconds=120)

Best Practices

  • Pre-determine Video Duration: FFmpeg's -progress log does not report the total input duration. Retrieve the input duration first using ffprobe to compute accurate percentage values:

    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
  • Prevent File Locking Issues: If the processing script and FFmpeg run on separate threads or processes, open the progress log in read-only mode ("r") to avoid file access conflicts.

  • File Cleanup: Ensure your application removes or truncates the progress.log file between different FFmpeg runs to prevent parsing outdated data from previous tasks.