Skip to main content

Python library to interface with HandBrakeCLI

Project description

pyhandbrake - Python library to interface with HandBrakeCLI

pyhandbrake is a small wrapper around HandBrakeCLI which I wrote when developing a project. Main features include:

  • Fully typed models representing handbrake output
  • Ability to load, modify and save presets
  • Ability to scan and rip titles
  • Live progress callbacks for supported commands

Installation

You will need a working copy of HandBrakeCLI as it is not included in this python package. For instructions on multiple OSes, see the installation guide. For ubuntu based distributions, it can be obtained with sudo apt-get install handbrake-cli.

From PyPI

pyhandbrake is available on PyPI, simply run pip install pyhandbrake

From the git repo

You can install python projects using pip directly from the git repo, in this instance with pip install git+https://github.com/dominicprice/pyhandbrake

From source

  1. Clone the repo with git clone https://github.com/dominicprice/pyhandbrake
  2. cd into the pyhandbrake directory
  3. Run pip install .

Usage

Although the package is named pyhandbrake, the actual name of the package you should import is handbrake (a slightly confusing but common convention with python packages). The package exposes one main object, HandBrake, which contains methods for interacting the handbrake cli:

  • HandBrake.version(...)
  • HandBrake.convert_title(...)
  • HandBrake.scan_title(...)
  • HandBrake.scan_all_titles(...)
  • HandBrake.get_preset(...)
  • HandBrake.list_presets(...)
  • HandBrake.load_preset_from_file(...)

Information about these function can be found in the docstrings on the methods, found in src/handbrake/init.py and information about the return types can be found in the src/handbrake/models directory.

Passing arguments to convert_title

Rather than accept all possible command line arguments, convert_title only allows you to set most options through a preset. Therefore you need to find out which preset setting corresponds to the given command line argument and set that value in a Preset object and add the preset to the search path by using it in the presets parameter.

Note that you should name the preset something unique, and then tell handbrake to use that preset by also passing the name to the preset argument, for example:

from handbrake import HandBrake

h = HandBrake()
# get the default CLI preset, but could also use
# h.get_preset("<builtin preset name>") to get any
# of the inbuilt presets, or h.load_preset("<path to preset>")
# to load a custom preset
preset = h.get_preset("CLI Default")

# a preset contains layers which are held in the `preset_list` field. The default
# presets all contain one layer so we only do our work on `preset_list[0]`
preset.preset_list[0]["PictureWidth"] = 100
preset.preset_list[0]["PictureHeight"] = 50
preset.preset_list[0]["PresetName"] = "my_preset"

h.convert_title("/path/to/input", "/path/to/output", "main", preset="my_preset", presets=[preset])

Handling progress updates

Methods related to reading titles accept a ProgressHandler argument. This should be a function which accepts a Progress model, and it is called every time handbrake emits a progress message allowing you to display information about the progress of the command, e.g.

from handbrake import HandBrake
from handbrake.models import Progress

def progress_handler(p: Progress):
  print(p.task_description, f"{int(p.percent)}%")

h = HandBrake()
h.rip_title("/path/to/input", "/path/to/output", "main", progress_handler=progress_handler)

Developing

pyhandbrake uses poetry as a toolchain. You should install poetry (via e.g. pipx install poetry) and then inside the project root run poetry install to create a virtual environment with all the dependencies.

Common project tasks are defined inside the Makefile:

  • make lint: Run the mypy type checker
  • make format: Run the code formatter
  • make test: Run the test suite
  • make sdist: Build the source distribution
  • make wheel: Build a python wheel

Troubleshooting

I do not really intend on actively maintaining this project unless I have to use it again, so future versions of handbrake may introduce breaking changes. If you notice this then pull requests would be very welcome! These notes are for future me as much as they are for any other interested readers.

I anticipate that the most likely thing to cause errors/unexpected output is if fields are added/removed/renamed from the JSON objects which handbrake outputs.

For added fields, pyhandbrake should silently ignore them - to include them you will need to modify the relevant model in the models subpackage to include the field. Note that handbrake uses pascal case for field names, but I have used snake case for the model field names. Pydantic automatically takes care of converting between these naming conventions, but will trip over capitalised abbreviations, (e.g. a field named SequenceID). In this case, you need to assign a Field value to the field with the full name handbrake uses as an alias parameter (e.g. sequence_id: str = Field(alias="SequenceID")).

For fields which are removed/renamed, a pydantic validation error will be emitted as the value would be required to populate the model. In this instance, you should assign the value to a Field instance with a default value and the deprecated flag (e.g. old_field_name: str = Field("", deprecated=True)). Note: if the field is a mutable type then you will need to use a default_factory instead of a value (e.g. old_field_name: list[str] = Field(default_factory=lambda: [], deprecated=True)). If the field has been renamed you can then create a new field with the new name as described in the paragraph above.

A more pernicious problem would be if the output of the handbrake program changes format. In this case the processing of the command output would need to be rewritten, you are welcome to do so but the logic should still be able to handle older versions of handbrake by i.e. checking the version and delegating to an appropriate function.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyhandbrake-1.0.0.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

pyhandbrake-1.0.0-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file pyhandbrake-1.0.0.tar.gz.

File metadata

  • Download URL: pyhandbrake-1.0.0.tar.gz
  • Upload date:
  • Size: 12.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for pyhandbrake-1.0.0.tar.gz
Algorithm Hash digest
SHA256 c2393ae1c13f5c8b42f8ee5ef22eb4af537dc684d3607ddc168a8b282bd6d619
MD5 3f2cbf60822952bf5e67fb4d7c5fb3ef
BLAKE2b-256 321c620ca3bc06dda62690c323f950bd3d4813c0998aa8981d1926cec6c5177f

See more details on using hashes here.

File details

Details for the file pyhandbrake-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pyhandbrake-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for pyhandbrake-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 433019933ca527f9f8dd8a2b267aa89d02775336dd403ea0f44d2a7c731702c5
MD5 88e93d46bd81f0303735a798f09f5c9c
BLAKE2b-256 ae606b212bbd2c5fccac616e866c182c279c5755d5dcb57ce1618839746e83d2

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page