Convert ffmpeg commands to use hardware acceleration
Project description
ffmpeg-hw-accel
A Python library that converts standard (software) ffmpeg commands into hardware-accelerated equivalents, automatically detecting available accelerators on the current machine and handling all compatibility differences between encoders.
The library only transforms command strings. Executing the command is always left to the caller.
Table of Contents
- Features
- Supported Hardware Accelerators
- Requirements
- Installation
- Quick Start
- Usage Guide
- Compatibility Rules
- Development
Features
- ๐ Auto-detection: queries your local
ffmpegbinary at startup to discover which hardware encoders are actually available - ๐ Command conversion: rewrites
-c:v,-preset,-crf,-tune, and other flags to their hardware-accelerated equivalents - ๐ก๏ธ Compatibility enforcement: automatically removes flags that are incompatible with the chosen accelerator (e.g.
-tunehas no meaning for NVENC) - โฉ๏ธ Automatic fallback: if the target accelerator is unavailable or conversion fails, the original command is returned unchanged (configurable)
- ๐๏ธ Singleton design: one instance per process; detection runs once at initialisation
- ๐ Strict typing: all parameters use enums; no magic strings internally
- ๐ Cross-platform: works on Linux, Windows, and macOS; available accelerators depend on the hardware present
Supported Hardware Accelerators
| Accelerator | Enum | Typical Platform | Example Codecs |
|---|---|---|---|
| Software (fallback) | HWAccelerator.NONE |
All | libx264, libx265 |
| NVIDIA NVENC | HWAccelerator.NVENC |
Windows, Linux | h264_nvenc, hevc_nvenc |
| Intel Quick Sync | HWAccelerator.QSV |
Windows, Linux | h264_qsv, hevc_qsv |
| AMD AMF | HWAccelerator.AMF |
Windows, Linux | h264_amf, hevc_amf |
| VAAPI | HWAccelerator.VAAPI |
Linux | h264_vaapi, hevc_vaapi |
| Apple VideoToolbox | HWAccelerator.VIDEOTOOLBOX |
macOS | h264_videotoolbox, hevc_videotoolbox |
| V4L2 M2M | HWAccelerator.V4L2 |
Linux (Raspberry Pi) | h264_v4l2m2m |
Requirements
- Python 3.11+
ffmpeginstalled and accessible on yourPATH(or provide the full path)- The hardware driver and SDK corresponding to the accelerator you want to use (e.g. NVIDIA drivers for NVENC)
Installation
pip install ffmpeg-hw-accel
Or with uv:
uv add ffmpeg-hw-accel
Quick Start
from ffmpeg_hw_accel import FFmpegHWAccel, HWAccelerator
# Initialise โ detects available hardware at this point
accel = FFmpegHWAccel.get_instance()
# See what was found
print(accel.available_accelerators)
# [<HWAccelerator.NONE: 'none'>, <HWAccelerator.NVENC: 'nvenc'>]
# Convert a command
original = "ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 22 -c:a aac output.mp4"
converted = accel.convert(original, HWAccelerator.NVENC)
print(converted)
# ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc -preset p6 -cq 22 -c:a aac -rc:v vbr -b:v 0 output.mp4
Usage Guide
Initialisation
FFmpegHWAccel is a singleton. The first call to get_instance() creates the instance and runs hardware detection. All subsequent calls return the same object.
from ffmpeg_hw_accel import FFmpegHWAccel
# Default โ uses "ffmpeg" from PATH, fallback enabled
accel = FFmpegHWAccel.get_instance()
# Custom ffmpeg binary
accel = FFmpegHWAccel.get_instance(
ffmpeg_binary="/usr/local/bin/ffmpeg", # full path or name on PATH
auto_fallback=True, # True = return original on any error (default)
)
| Parameter | Type | Default | Description |
|---|---|---|---|
ffmpeg_binary |
str |
"ffmpeg" |
Path or name of the ffmpeg executable |
auto_fallback |
bool |
True |
Return the original command unchanged if conversion fails or the accelerator is unavailable |
Detecting Available Accelerators
# Full list
print(accel.available_accelerators)
# [<HWAccelerator.NONE: 'none'>, <HWAccelerator.NVENC: 'nvenc'>]
# Check a specific accelerator
accel.is_available(HWAccelerator.NVENC) # True
accel.is_available(HWAccelerator.VIDEOTOOLBOX) # False (not macOS)
# List codecs available for a given accelerator
codecs = accel.get_available_codecs(HWAccelerator.NVENC)
# [<VideoCodec.H264_NVENC: 'h264_nvenc'>, <VideoCodec.HEVC_NVENC: 'hevc_nvenc'>]
Converting a Command
Pass any standard ffmpeg command string and a target HWAccelerator:
original = (
"ffmpeg -i input.mp4 "
"-c:v libx264 -preset medium -tune film -crf 23 "
"-c:a aac -b:a 192k output.mp4"
)
# NVENC
print(accel.convert(original, HWAccelerator.NVENC))
# ffmpeg -hwaccel cuda -i input.mp4
# -c:v h264_nvenc -preset p5 -cq 23
# -c:a aac -b:a 192k -rc:v vbr -b:v 0 output.mp4
# (-tune film removed โ not supported by NVENC)
# QSV
print(accel.convert(original, HWAccelerator.QSV))
# ffmpeg -hwaccel qsv -hwaccel_output_format qsv -i input.mp4
# -c:v h264_qsv -preset medium -global_quality 23
# -c:a aac -b:a 192k output.mp4
# VAAPI (Linux)
print(accel.convert(original, HWAccelerator.VAAPI))
# ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -i input.mp4
# -c:v h264_vaapi -qp 23
# -c:a aac -b:a 192k -vf format=nv12|vaapi,hwupload output.mp4
# (-preset and -tune removed โ VAAPI has no preset concept)
# VideoToolbox (macOS)
print(accel.convert(original, HWAccelerator.VIDEOTOOLBOX))
# ffmpeg -i input.mp4
# -c:v h264_videotoolbox -q:v 23
# -c:a aac -b:a 192k output.mp4
# (-preset, -tune, -crf all removed โ not supported)
# AMF (AMD)
print(accel.convert(original, HWAccelerator.AMF))
# ffmpeg -i input.mp4
# -c:v h264_amf -preset balanced -qp_i 23
# -c:a aac -b:a 192k output.mp4
Fallback Behaviour
auto_fallback=True (default)
The original command is returned unchanged when:
- The requested accelerator is not detected on the machine
- An exception occurs during conversion
accel = FFmpegHWAccel.get_instance(auto_fallback=True)
cmd = "ffmpeg -i input.mp4 -c:v libx264 output.mp4"
# VAAPI not available on this machine โ returns original silently
result = accel.convert(cmd, HWAccelerator.VAAPI)
print(result)
# "ffmpeg -i input.mp4 -c:v libx264 output.mp4"
auto_fallback=False
Raises exceptions instead of silently falling back:
from ffmpeg_hw_accel import FFmpegHWAccel, HWAccelerator
FFmpegHWAccel.reset_instance()
accel = FFmpegHWAccel.get_instance(auto_fallback=False)
cmd = "ffmpeg -i input.mp4 -c:v libx264 output.mp4"
try:
result = accel.convert(cmd, HWAccelerator.VAAPI)
except ValueError as e:
print(e)
# Hardware accelerator 'vaapi' is not available on this machine.
# Available: ['none', 'nvenc']
Executing the Converted Command
The library only produces a command string. Running it is your responsibility:
import subprocess
import shlex
from ffmpeg_hw_accel import FFmpegHWAccel, HWAccelerator
accel = FFmpegHWAccel.get_instance()
original = "ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 22 output.mp4"
hw_cmd = accel.convert(original, HWAccelerator.NVENC)
try:
subprocess.run(shlex.split(hw_cmd), check=True)
print("Encoding complete.")
except subprocess.CalledProcessError as e:
print(f"Hardware encoding failed: {e}")
# Manually fall back to software
subprocess.run(shlex.split(original), check=True)
Selecting the Best Available Accelerator
from ffmpeg_hw_accel import FFmpegHWAccel, HWAccelerator
def get_best_accel(accel: FFmpegHWAccel) -> HWAccelerator:
preference = [
HWAccelerator.NVENC,
HWAccelerator.QSV,
HWAccelerator.VIDEOTOOLBOX,
HWAccelerator.AMF,
HWAccelerator.VAAPI,
HWAccelerator.V4L2,
HWAccelerator.NONE, # software fallback โ always available
]
return next(a for a in preference if accel.is_available(a))
accel = FFmpegHWAccel.get_instance()
best = get_best_accel(accel)
original = "ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -c:a aac output.mp4"
final_cmd = accel.convert(original, best)
print(f"Selected: {best.value}")
print(f"Command: {final_cmd}")
Resetting the Singleton
Useful when you need to switch ffmpeg binary or re-run detection (e.g. in tests):
FFmpegHWAccel.reset_instance()
# Next call creates a fresh instance with new detection
accel = FFmpegHWAccel.get_instance(ffmpeg_binary="/opt/homebrew/bin/ffmpeg")
Compatibility Rules
The table below summarises what each accelerator removes or transforms:
| Flag | NVENC | QSV | VAAPI | VideoToolbox | AMF | V4L2 |
|---|---|---|---|---|---|---|
-tune |
โ removed | โ removed | โ removed | โ removed | โ removed | โ removed |
-x264opts |
โ removed | โ removed | โ removed | โ removed | โ removed | โ removed |
-x264-params |
โ removed | โ removed | โ removed | โ removed | โ removed | โ removed |
-preset |
โ๏ธ remapped (p1โp7) | โ๏ธ remapped | โ removed | โ removed | โ๏ธ remapped | โ removed |
-crf |
โ๏ธ โ -cq |
โ๏ธ โ -global_quality |
โ๏ธ โ -qp |
โ removed | โ๏ธ โ -qp_i |
โ removed |
-profile:v |
โ kept | โ kept | โ removed | โ removed | โ kept | โ kept |
-c:v libx264 |
โ๏ธ โ h264_nvenc |
โ๏ธ โ h264_qsv |
โ๏ธ โ h264_vaapi |
โ๏ธ โ h264_videotoolbox |
โ๏ธ โ h264_amf |
โ๏ธ โ h264_v4l2m2m |
-c:v libx265 |
โ๏ธ โ hevc_nvenc |
โ๏ธ โ hevc_qsv |
โ๏ธ โ hevc_vaapi |
โ๏ธ โ hevc_videotoolbox |
โ๏ธ โ hevc_amf |
โ๏ธ โ hevc_v4l2m2m |
Development
Setup
This project uses uv for dependency management.
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone the repository
git clone https://github.com/your-username/ffmpeg-hw-accel.git
cd ffmpeg-hw-accel
# Install dependencies including dev extras
uv sync --extra dev
Running Tests
# Run all tests
uv run pytest
# With coverage report
uv run pytest --cov=src/ffmpeg_hw_accel --cov-report=term-missing
# Run a specific test file
uv run pytest tests/test_converter.py
# Run a specific test case
uv run pytest tests/test_converter.py::TestFFmpegCommandConverter::test_nvenc_replaces_libx264_codec
# Verbose output
uv run pytest -v
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ffmpeg_hw_accel-0.1.0.tar.gz.
File metadata
- Download URL: ffmpeg_hw_accel-0.1.0.tar.gz
- Upload date:
- Size: 39.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df196ca66969e9fff112715bb89817aebbcb3ba11e703030c401a8432123e6bd
|
|
| MD5 |
adf5d3f2b291dc3e4cdb8a14c41c2a77
|
|
| BLAKE2b-256 |
e3ae2f85b697b52d17ef39e2f7ec893a6b8583763d97b8d335d71d0e72ffd1a3
|
File details
Details for the file ffmpeg_hw_accel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ffmpeg_hw_accel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.15 {"installer":{"name":"uv","version":"0.9.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81c863b653665d224dc3031b5aa6a3a742774fc71593f08fd31ab013e2951ebd
|
|
| MD5 |
70160bbbfd947c9b8c0ccefa81530625
|
|
| BLAKE2b-256 |
c0a7a377f420f816d9fe3305886f08cb7f7633d850c863803700294b0ddf75a7
|