How to Run FFmpeg and Parse Progress in Python
Running FFmpeg within Python allows you to automate video processing
tasks, but tracking the progress of these operations is crucial for user
experience. This article demonstrates how to use Python’s built-in
subprocess module to execute FFmpeg commands and parse its
real-time output to calculate and display the conversion progress.
The Approach: FFmpeg
-progress Flag
While you can parse FFmpeg’s standard error stream
(stderr), its layout can change and is difficult to parse
reliably. The most robust method is to use FFmpeg’s
-progress option. By passing -progress pipe:1,
FFmpeg writes easy-to-parse key-value pairs directly to standard output
(stdout), which your Python script can read
line-by-line.
Python Implementation
The following complete script first retrieves the total duration of
the input video using ffprobe (part of the FFmpeg suite),
then runs the conversion command and calculates the percentage
completion in real-time.
import subprocess
import os
def get_video_duration(input_file):
"""Retrieve the total duration of the video in seconds using ffprobe."""
cmd = [
'ffprobe',
'-v', 'error',
'-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1',
input_file
]
try:
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
return float(result.stdout.strip())
except (subprocess.CalledProcessError, ValueError):
raise RuntimeError(f"Could not retrieve duration for file: {input_file}")
def convert_video_with_progress(input_file, output_file):
"""Convert video using FFmpeg and print real-time progress to the console."""
if not os.path.exists(input_file):
print(f"Error: Input file '{input_file}' does not exist.")
return
# Get total duration to calculate percentage
total_duration = get_video_duration(input_file)
print(f"Total Duration: {total_duration:.2f} seconds")
# Command with -progress pipe:1 to output progress metrics to stdout
cmd = [
'ffmpeg', '-y',
'-i', input_file,
'-progress', 'pipe:1',
'-nostats',
output_file
]
# Start the FFmpeg process
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
text=True,
bufsize=1
)
# Read progress output line by line
for line in process.stdout:
if 'out_time_us' in line:
# out_time_us provides the current processed time in microseconds
try:
microseconds = int(line.split('=')[1].strip())
current_time = microseconds / 1_000_000.0
percentage = (current_time / total_duration) * 100
# Cap percentage at 100% (metadata processing can sometimes cause slight overflow)
percentage = min(percentage, 100.0)
print(f"Progress: {percentage:.2f}%", end='\r')
except ValueError:
continue
process.wait()
if process.returncode == 0:
print("\nConversion completed successfully!")
else:
print(f"\nConversion failed with exit code {process.returncode}")
# Example Usage
if __name__ == "__main__":
convert_video_with_progress("input.mp4", "output.mkv")How the Code Works
- Duration Detection: The
get_video_durationfunction callsffprobeto query the format metadata and returns the video duration as a float in seconds. - Subprocess Initialization:
subprocess.Popenstarts the FFmpeg process asynchronously. Settingstdout=subprocess.PIPEredirects the progress information to Python, whilestderr=subprocess.DEVNULLsuppresses the default diagnostic output.bufsize=1enables line-buffering to ensure real-time updates. - Progress Parsing: FFmpeg regularly outputs status
lines. The script looks specifically for
out_time_us(output time in microseconds). By dividing this value by1,000,000, the script gets the current elapsed playback time in seconds. - Percentage Calculation: The elapsed time is divided
by the total duration and multiplied by 100 to yield the current
completion percentage, which is printed in place using the carriage
return (
\r) character.