How to Mock FFmpeg subprocess Calls in Python

Compress a video with ffmpeg while mocking subprocess.run to test the command construction without executing the actual encoder.

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 14 views 0 copies

Python code

28 lines
Python 3.9+
import subprocess
from unittest.mock import Mock, patch


def compress_video(input_path: str, output_path: str, crf: int = 23) -> None:
    """Compress a video using ffmpeg with a given CRF (quality) value."""
    command = [
        "ffmpeg",
        "-i", input_path,
        "-c:v", "libx264",
        "-crf", str(crf),
        "-preset", "fast",
        output_path
    ]
    subprocess.run(command, check=True)


if __name__ == "__main__":
    # Mock subprocess.run to avoid actually invoking ffmpeg
    with patch("subprocess.run") as mock_run:
        mock_run.return_value = None
        compress_video("input.mp4", "output.mp4", crf=28)

        # Verify the command was constructed correctly and called once
        mock_run.assert_called_once()
        called_command = mock_run.call_args[0][0]
        print("Command:", " ".join(called_command))
        print("Called with check=True:", mock_run.call_args.kwargs["check"])

Output

stdout
Command: ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast output.mp4
Called with check=True: True

How it works

This script defines a compress_video function that builds an ffmpeg command list and executes it with subprocess.run. The patch context manager replaces subprocess.run with a mock, preventing any real system call. Inside the patch, the function is invoked, and assert_called_once() verifies that exactly one subprocess call was made. The mock's call_args captures the actual command tuple and keyword arguments, allowing us to inspect and print the generated command and the check flag. This pattern keeps your test environment safe and fast while verifying command construction logic.

Common mistakes

  • Not specifying `check=True` when you want subprocess errors to raise an exception.
  • Forgetting that `patch("subprocess.run")` must be on the same module path where it is used (here, `subprocess.run`).
  • Assuming `mock_run.call_args[0][0]` holds a string; it actually holds a list of command tokens.

Variations

  1. Use `unittest.mock` with `assert_called_once_with` to check exact command and kwargs.
  2. Use `subprocess.check_output` instead of `subprocess.run` if you need to capture ffmpeg's stderr output.

Real-world use cases

  • Writing unit tests for a batch video-processing pipeline without invoking heavy external tools.
  • Validating that your script builds the correct ffmpeg arguments before deploying to production servers.
  • Simulating ffmpeg failures in CI to test error-handling logic without installing ffmpeg on every runner.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.