Monitor FFmpeg Progress with Stdout Redirection

Monitoring the progress of an FFmpeg encoding process through standard output (stdout) requires routing FFmpeg's internal progress reporting away from its default standard error (stderr) stream. This article explains why FFmpeg defaults to stderr, how to use the built-in -progress flag to pipe structured metrics directly to stdout, and how to parse the resulting stream using shell tools or custom scripts.

The Problem with Default FFmpeg Output

By default, FFmpeg prints all informational logs, encoding statistics, and errors to stderr, keeping stdout reserved for raw media output when piping. Because interactive progress displays continuously update using carriage returns (\r), capturing and parsing standard terminal output can be erratic and difficult to process reliably.

The Solution: Using -progress pipe:1

FFmpeg includes a dedicated progress option (-progress) that periodically emits machine-readable progress metrics to a specified URL or file descriptor. By passing pipe:1, you direct this telemetry directly to stdout.

To ensure clean output, combine this with -nostats (to disable default console updates) and -loglevel error (to prevent non-critical log messages from cluttering stderr).

Basic Command Syntax

ffmpeg -loglevel error -nostats -i input.mp4 -progress pipe:1 output.mkv

Understanding the Output Format

When redirected to stdout, FFmpeg produces key-value pairs separated by equal signs, ending with a progress= line for each update interval:

frame=1240
fps=59.80
stream_0_0_q=28.0
bitrate= 2450.2kbits/s
total_size=15728640
out_time_us=20666667
out_time_ms=20666667
out_time=00:00:20.666667
dup_frames=0
drop_frames=0
speed=0.997x
progress=continue

Key fields include:

  • out_time_us: The current encoded duration in microseconds (most reliable for calculating completion percentages).
  • out_time: Human-readable timestamp (HH:MM:SS.microsecond).
  • frame: Total number of video frames processed so far.
  • speed: Current processing speed relative to real-time playback.
  • progress: Indicates processing state; displays continue during the encode and end upon completion.

Processing Progress in Real Time

Example: Filtering with Grep

To isolate just the current timestamp in real time:

ffmpeg -loglevel error -nostats -i input.mp4 -progress pipe:1 output.mkv | grep --line-buffered "out_time="

Example: Parsing with Python

You can read stdout line-by-line using Python's subprocess module:

import subprocess

command = [
    "ffmpeg",
    "-loglevel", "error",
    "-nostats",
    "-i", "input.mp4",
    "-progress", "pipe:1",
    "output.mp4"
]

process = subprocess.Popen(
    command,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    universal_newlines=True
)

for line in process.stdout:
    line = line.strip()
    if "=" in line:
        key, value = line.split("=", 1)
        if key == "out_time":
            print(f"Current Position: {value}")
        elif key == "progress" and value == "end":
            print("Encoding Complete.")

process.wait()

Calculating Completion Percentage

To calculate a percentage completion value:

  1. Determine the total duration of the input file before encoding using ffprobe:

    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
  2. Convert that duration into microseconds (multiply seconds by 1,000,000).

  3. Read the out_time_us value from the pipe:1 output stream.

  4. Compute the percentage: (out_time_us / total_duration_us) * 100.