Skip to main content

The missing CLI and Python library for DaVinci Resolve. Declarative, scriptable, LLM-friendly.

Project description

dvr

PyPI version Python versions CI Docs License: MIT

The missing CLI and Python library for DaVinci Resolve.

Declarative. Scriptable. LLM-friendly. No more silent None returns.

pip install dvr
$ dvr timeline inspect
{
  "name": "MyShow_207_R2",
  "fps": 24.0,
  "duration_frames": 86400,
  "tracks": {
    "video": [{"index": 1, "name": "V1", "clips": 1, "enabled": true}, ...],
    "audio": [{"index": 1, "name": "A1", "clips": 4, "subtype": "stereo"}, ...]
  },
  "markers": [...],
  "color": {"science": "DaVinci YRGB Color Managed v2", "input": "Rec.2020", ...}
}

Why this exists

DaVinci Resolve has a powerful Python scripting API. It's also painful:

  • Silent failures everywhere. AddRenderJob() returns None on success or failure — good luck.
  • String-keyed settings with undocumented valid values.
  • No batch operators. You loop everything.
  • macOS connection footguns. Resolve binds to LAN IP; vanilla scriptapp('Resolve') returns None.
  • Chain navigation. Every .Get*() can return None. One typo and you're traversing nothing.
  • 20+ export formats behind magic enum constants.

dvr wraps the API with a clean object model, idempotent operations, decoded errors, structured I/O, and a CLI that's pleasant for humans and parseable by LLM agents.

Three ways to use it

1. Python library

from dvr import Resolve

r = Resolve()  # auto-connects, handles macOS LAN-IP quirk

with r.project.use("MyShow_207"):
    tl = r.timeline.current
    print(tl.inspect())                      # one call, full state

    # Query language operates on inspected state
    bad = tl.clips.where(lambda c: c.duration < 12)
    for clip in bad:
        clip.add_marker(color="red", note="too short")

    job = r.render.submit(preset="delivery")
    job.wait()                               # blocks with progress
    print(job.output_path)

2. CLI

$ dvr project ensure MyShow_207 --color rec2020_pq_4000 --fps 24
$ dvr timeline inspect | jq '.tracks.video[].clips'
$ dvr render submit --preset delivery --wait --stream
{"job_id": "abc", "status": "rendering", "pct": 12, "eta_s": 240}
{"job_id": "abc", "status": "rendering", "pct": 24, "eta_s": 210}
{"job_id": "abc", "status": "complete", "output": "/path/out.mov"}

3. MCP server (for LLM agents)

$ dvr mcp serve              # exposes the library as MCP tools

LLM agents call typed tools directly — no shell parsing, no silent failures.

Five things that make it fundamentally better than the raw API

  1. One inspect() call replaces ten API calls. Full structured state in a single round-trip.
  2. Idempotent operations. project.ensure(), timeline.ensure(), bin.ensure() — re-run anything safely.
  3. Decoded errors. Every failure carries cause, fix, and state. No more None.
  4. Declarative specs. dvr apply project.dvr.yaml reconciles state. kubectl apply for DaVinci.
  5. Persistent connection. dvr serve keeps Resolve warm — sequential commands run in <100ms.

Install

Channel Command
Homebrew (macOS / Linux) brew install mhadifilms/tap/dvr
PyPI pip install dvr
pipx pipx install dvr
uv uv tool install dvr
From source git clone https://github.com/mhadifilms/dvr && cd dvr && pip install -e ".[dev]"

Optional extras

pip install "dvr[mcp]"            # MCP server for LLM agents
pip install "dvr[docs]"           # docs site dependencies
pip install "dvr[dev]"            # dev (ruff, mypy, pytest)

Homebrew details

dvr ships via my personal tap at mhadifilms/homebrew-tap. The recommended pattern is to tap once, then use the bare command:

brew tap mhadifilms/tap
brew install dvr            # works after the tap is installed

Or, if you only ever want to install once and don't care about updates:

brew install mhadifilms/tap/dvr

brew install dvr says "no formula"? That's expected if you haven't tapped yet. Homebrew only searches homebrew/core by default; our formula lives in our personal tap. Run brew tap mhadifilms/tap and try again.

Requirements

  • Python 3.10+ (matches Resolve's embedded Python on current versions)
  • DaVinci Resolve Studio 18.5+ — external scripting is a Studio-only feature. Blackmagic Design sells Studio as a one-time $295 perpetual license or via Blackmagic Cloud at $30/month per seat.
  • macOS, Windows, or Linux

dvr auto-discovers Resolve's scripting library on each platform. No environment variables needed for typical installs.

The free edition of DaVinci Resolve cannot be scripted from outside the app (Blackmagic restricted this in v19.1+). If you're evaluating dvr without Studio, use --dry-run flags on apply and explore the schema/inspection commands — they work without a live connection.

Status

Pre-1.0. The public API may change. See CHANGELOG.md for breaking changes.

License

MIT — see LICENSE.

Contributing

Issues and pull requests welcome. The project's API surface is large; contributions covering edge cases on Windows / Linux are especially valuable. See CONTRIBUTING.md for setup and conventions.


dvr is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Blackmagic Design. "DaVinci" and "DaVinci Resolve" are trademarks of Blackmagic Design Pty Ltd.

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

dvr-1.1.0.tar.gz (111.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dvr-1.1.0-py3-none-any.whl (107.7 kB view details)

Uploaded Python 3

File details

Details for the file dvr-1.1.0.tar.gz.

File metadata

  • Download URL: dvr-1.1.0.tar.gz
  • Upload date:
  • Size: 111.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dvr-1.1.0.tar.gz
Algorithm Hash digest
SHA256 9483cf1991dde62c259d4ee6307a58610552e659813f91b9ec5f88e96ece78f9
MD5 a4d346384e05d2b8eb64a10c48a31518
BLAKE2b-256 6ba36ac274dbb3f4793fdd13789a103b9c581545919832591cb3b33f2c49ec94

See more details on using hashes here.

Provenance

The following attestation bundles were made for dvr-1.1.0.tar.gz:

Publisher: release.yml on mhadifilms/dvr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dvr-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: dvr-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 107.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dvr-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d0aacada99cac391b0ef68030572c8831c77dca7c4a1928f2a3858d20e62569e
MD5 7804c22619165a6be64d6a5e4be79869
BLAKE2b-256 560ff253eeae2f812d8781941c8b6130cf4056c83f8cdf2418f5cb3af0eadcb5

See more details on using hashes here.

Provenance

The following attestation bundles were made for dvr-1.1.0-py3-none-any.whl:

Publisher: release.yml on mhadifilms/dvr

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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