python-ffmpeg
Python binding for FFmpeg with both synchronous and asyncio-native APIs
Repository Health
Technical Analysis
python-ffmpeg is a Python binding for FFmpeg that wraps the ffmpeg command-line binary behind a fluent, chainable Python API, offered in both a synchronous flavor and an asyncio-native ffmpeg.asyncio variant. Instead of hand-building shell command strings, developers chain .option(), .input(), and .output() calls to construct a transcoding, recording, or streaming pipeline, then call .execute() (or await it) to run FFmpeg as a subprocess.
The library exposes an event-based progress API (Progress events with frame/time/speed data) so callers can monitor or terminate long-running FFmpeg jobs mid-execution, which makes it well suited for use cases like recording an RTSP stream until a condition is met, or reporting transcoding progress in a UI.
What You Get
- A fluent, chainable builder API for constructing FFmpeg commands (
.option(),.input(),.output()) without hand-building shell strings - Both synchronous (
ffmpeg.FFmpeg) and asyncio-native (ffmpeg.asyncio.FFmpeg) execution APIs - Structured
Progressevents (frame, time, speed, bitrate) parsed from FFmpeg’s stderr for monitoring or early-terminating long-running jobs - Support for common workflows: transcoding, recording from RTSP/network sources, and other FFmpeg-driven media pipelines
- Typed error handling via a dedicated
errorsmodule surfacing FFmpeg failures as Python exceptions
Common Use Cases
- Transcoding video files (codec/resolution/bitrate conversion) from a Python script or web service without shelling out manually
- Recording an RTSP camera or network stream to disk with a programmatic stop condition (e.g. after N frames or a time limit)
- Building a media-processing microservice that reports live transcoding progress to a UI or job queue
- Scripting batch FFmpeg jobs (thumbnailing, format conversion, audio extraction) as part of a larger media pipeline
Under The Hood
Architecture: The core FFmpeg class (ffmpeg/ffmpeg.py) accumulates a command specification from chained .option()/.input()/.output() calls, then .execute() builds the actual argument list and spawns the ffmpeg binary as a subprocess. ffmpeg/statistics.py and ffmpeg/progress.py parse FFmpeg’s streaming stderr output into structured Progress objects dispatched through a small event-emitter (.on("progress", ...)), and ffmpeg/asyncio/ mirrors the same builder API on top of asyncio.subprocess for non-blocking execution. ffmpeg/protocol.py and ffmpeg/file.py handle input/output stream and file-like abstractions, with errors.py translating non-zero FFmpeg exits into typed exceptions.
Tech Stack: Pure Python, packaged with setuptools (both pyproject.toml and setup.py/setup.cfg present), formatted with black and isort (line length 120). The library has no runtime dependency on FFmpeg’s C libraries — it shells out to a pre-installed ffmpeg binary the user must provide separately.
Code Quality: 13 test files under tests/, with a GitHub Actions wheel-build workflow badge in the README indicating CI coverage for packaging. The codebase is small and modularly split by concern (options, progress parsing, protocol, errors), which keeps the surface easy to audit, though development activity has slowed considerably since the last push in mid-2024.
API Design: The chainable, CLI-mirroring builder syntax (.input(...).output(...)) reads naturally to anyone already familiar with FFmpeg’s command-line flags, and offering an async variant with an identical API surface (ffmpeg.asyncio.FFmpeg) means switching between sync and async code paths requires only an import change. Full documentation lives on Read the Docs rather than entirely in the README, and the RTSP recording example in the README doubles as a practical quickstart for the event-based progress API.