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.mp4FFmpeg 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 by1,000,000to 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.0xmeans twice as fast as real-time).progress: Emitscontinuewhile running andendwhen 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
-progresslog does not report the total input duration. Retrieve the input duration first usingffprobeto compute accurate percentage values:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4Prevent 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.logfile between different FFmpeg runs to prevent parsing outdated data from previous tasks.