Search and browse the EXR Converter docs

Blackmagic RAW support

EXR Converter can decode Blackmagic RAW (.braw) clips when built against the official Blackmagic RAW SDK. Without the SDK bridge, .braw is recognized in the UI but conversion fails with a clear “SDK missing” message.

Related: CLI · GUI · R3D / N-RAW · AGENTS.md


What you get

ItemBehavior
Formats.braw
DecodeOfficial OpenEXRTranscode default: Linear gamma + ACES AP0 gamut, post-3D LUT disabled, RGBF32
OCIOAuto-detect source space prefers ACES2065-1 (lin_ap0) on the bundled ACES Studio config
OutputSame video→EXR pipeline (EXR compression, scale ladder, frame range, workers)
GPUmacOS Metal (then OpenCL if Metal is unavailable). Windows / Linux: CUDA, then OpenCL. CPU fallback if GPU setup fails or decoder libs are missing. Force CPU with EXR_CONVERTER_BRAW_CPU=1.
PreviewSequence player + video browser (half-res decode for scrub)
ThumbnailsGrid thumbs via eighth-res decode
InspectVideo-browser Inspect reads clip metadata through the SDK, not PyAV
MetadataClip + per-frame timecode written to EXR as exrconverter:braw:* attrs

Scale maps to the SDK resolution ladder (full / half / quarter / eighth). Odd scale factors may apply a small software resize after decode.

The SDK is not used as a camera-look / BMD Film pipeline. We force Linear + ACES AP0 so the pixels match scene-referred ACES interchange. Clip sidecar looks (BMD Film, Rec.709, 3D LUT) are not applied. If you need those looks, transcode with DaVinci Resolve / the official sample -m path instead.


License (read this)

The Blackmagic RAW SDK is proprietary (Blackmagic Design). It is free to download from the developer site after accepting their license. Terms live in the Developer License that ships with the SDK package. Always verify the copy you downloaded.

Summary of constraints that affect this project (not a substitute for the legal text):

  • Use the SDK to build applications that decode .braw.
  • You may typically redistribute runtime API libraries in object form together with software built on the SDK (Developer License 1.1(d) in recent packages). Confirm that clause in your SDK.
  • You must not redistribute the SDK package as a whole, headers, samples, or documentation. Users obtain the SDK from Blackmagic Design.
  • Do not reverse-engineer the libraries or file format.

Do not commit the Blackmagic RAW SDK tree into the public git repository. The BRAW bridge source is not in this public repo: it is proprietary and lives in the private derek-rein/braw-sdk-private repo (bridge/), fetched at build time by scripts/build_braw_bridge.py. This repo only contains the build wrapper and Python ctypes glue (src/core/braw/).


Where the full SDK lives (maintainers)

LocationPurpose
~/.braw-sdk/ or ~/code/braw-sdk-private/BlackmagicRAWSDK-6.0/Local full SDK unpack (headers + runtime Libraries)
Private GitHub repo derek-rein/braw-sdk-privateREADME + package script only (no SDK blobs in git)
Private Release tag sdk-6.0 asset BlackmagicRAWSDK-6.0-full.tar.gzCI build-time feed for public exr-converter Releases

Public GitHub Release artifacts for EXR Converter may include only:

  • libbraw_bridge.{dylib,so,dll}
  • Blackmagic Libraries/ runtime dynamic libraries (and the macOS .framework binary)

…under a private app folder (Contents/Frameworks/braw/ on macOS, …/braw/ elsewhere), never headers, samples, profile.braw, or SDK documentation.

Refresh the private CI feed

# After unpacking a new official SDK as BlackmagicRAWSDK-6.0/
cd ~/code/braw-sdk-private
./scripts/package_release.sh
# retags/uploads BlackmagicRAWSDK-6.0-full.tar.gz to release sdk-6.0

Developer setup (local)

# Unpack the official SDK (example slim layout):
#   ~/.braw-sdk/slim/Linux/Include/BlackmagicRawAPI.h
#   ~/.braw-sdk/slim/Linux/Libraries/libBlackmagicRawAPI.so

export BRAW_SDK_ROOT="$HOME/.braw-sdk/slim"
cd /path/to/exr-converter
make braw-bridge
# → build/braw/libbraw_bridge.so + build/braw/redistributable/

# Or pull the same tarball CI uses (needs gh auth or BRAW_SDK_READ_TOKEN):
make braw-sdk-fetch   # → .braw-sdk/BlackmagicRAWSDK-6.0 (gitignored)
make braw-bridge

Discovery (first match wins):

LocationNotes
BRAW_SDK_ROOTUnpacked SDK root (slim/ or Linux/-style)
~/.braw-sdk/slim or ~/.braw-sdkLocal stash
/usr/lib64/blackmagic/BlackmagicRAWSDKConventional Linux install
/usr/lib/blackmagic/BlackmagicRAWSDKAlternate FHS path
/opt/blackmagic/BlackmagicRAWSDKOptional local drop

Override at runtime:

Env varMeaning
BRAW_SDK_ROOTUnpacked SDK root for building the bridge
EXR_CONVERTER_BRAW_BRIDGEPath to libbraw_bridge.* (or its directory)
EXR_CONVERTER_BRAW_LIBS / BRAW_SDK_LIBSFolder containing libBlackmagicRawAPI.*
BRAW_SDK_READ_TOKENDedicated PAT that can download the private BRAW Release asset
EXR_CONVERTER_BRAW_CPUSet to 1 to skip GPU decode (CPU only)

Convert:

uv run python main.py video2exr -i /path/clip.braw -o /tmp/exr_out \
  --src ACES2065-1 --dst ACEScg --frame-range 1

Color (what the SDK returns)

The bridge asks the SDK for scene-linear, ACES AP0 gamut, no post-LUT, interleaved RGB float32 output.

On the bundled ACES Studio Config v4, that working space is ACES2065-1 (aliases: ACES - ACES2065-1, lin_ap0). Auto-detect tries those names in order.

This is linear scene-referred AP0, not Blackmagic Design Film / Wide Gamut log. Values can be above 1.0.


Packaging layout (shipped)

macOS:  EXR Converter.app/Contents/Frameworks/braw/
Linux:  <dist>/braw/
Windows:<dist>/braw/
          libbraw_bridge.*
          BlackmagicRawAPI.framework/          (macOS; Metal + runtime)
          libBlackmagicRawAPI.*  libDecoder*.*  libInstructionSetServices*.*

The macOS .framework is installed under Contents/Frameworks/, not Contents/MacOS/. A nested framework beside the executable makes the outer .app look like both an app and a framework. The SDK 6.0 BlackmagicRawAPI.framework tree is also not a clean versioned framework (flattened Versions/Current, a real top-level Resources/, Contents/, or nested .bundle / helper .app), so codesign --deep on the framework itself fails with bundle format is ambiguous even under Frameworks/braw/. Release copies the framework preserving symlinks, restores Versions/Current links, then signs Mach-Os inside-out without --deep (Developer ID hardened runtime when the release signing secrets are set, otherwise ad-hoc). GPU decoder binaries stay inside the framework / braw/ folder.

Only runtime dynamic libraries from the SDK Libraries/ folder plus our bridge, including GPU decoder libs (libDecoderCUDA / libDecoderOpenCL / DecoderMetal). Never headers, samples, profile.braw, or SDK documentation.


CI / GitHub Release builds

The Release workflow (Nuitka multi-OS):

  1. If secret BRAW_SDK_READ_TOKEN is set → download sdk-6.0 / BlackmagicRAWSDK-6.0-full.tar.gz from the private repo.
  2. Build libbraw_bridge (macOS / Linux / Windows + MSVC). On Windows the official SDK ships BlackmagicRawAPI.idl; the build runs midl to generate BlackmagicRawAPI.h and BlackmagicRawAPI_i.c (COM IID definitions) into build/braw/win_include/ (not into the SDK tree), then compiles the IID file with the bridge and dispatch sources.
  3. After Nuitka, copy bridge + runtime Libraries only into the private braw/ folder (Contents/Frameworks/braw/ on macOS .app so BlackmagicRawAPI.framework is not nested under Contents/MacOS).
  4. Refuse the build if headers / .a / .lib appear under that folder, or if a .framework remains under Contents/MacOS.
  5. Re-sign with scripts/macos_codesign.py: move non-Mach-O files from Contents/MacOS to Contents/Resources (relative symlinks stay so OCIO configs, pyproject.toml, and package data still resolve), then sign Mach-Os deepest-first, then each .framework without --deep, then the outer .app (also without --deep). Developer ID signing uses the hardened runtime and a secure timestamp; verification of that signature uses codesign --verify --deep --strict. Without the certificate secrets the same script ad-hoc signs and notarization is skipped. Refuse a .framework under Contents/MacOS.

If the secret is missing, Release still publishes the app without BRAW support (.braw convert reports SDK missing, same as R3D).

The bridge (private repo) handles per-platform SDK ABI differences. A tag-only re-run of Release rebuilds the tagged commit. To pick up a bridge compile hotfix already on main without moving the tag:

gh workflow run Release --ref main -f tag=v0.10.0 -f source_ref=main
# Dedicated fine-grained PAT with read on derek-rein/braw-sdk-private Releases
gh secret set BRAW_SDK_READ_TOKEN --repo derek-rein/exr-converter

Local make bundle builds and installs the runtime when BRAW_SDK_ROOT is set or after make braw-sdk-fetch.


Troubleshooting

SymptomFix
BRAW bridge library not foundmake braw-bridge / set EXR_CONVERTER_BRAW_BRIDGE
Blackmagic RAW runtime libraries not foundSet EXR_CONVERTER_BRAW_LIBS to the SDK Libraries folder
CI skips BRAWSecret BRAW_SDK_READ_TOKEN not set or cannot read private release
BRAW factory / runtime load failedWrong folder (must contain libBlackmagicRawAPI.so / .dylib / .dll)
Wrong colorsUse ACES2065-1 source. Decode is Linear AP0, not BMD Film
._….braw in browsermacOS AppleDouble metadata, hidden from the video browser
Convert log says CPU on a GPU machineGPU init failed (Metal / CUDA / OpenCL). Rebuild make braw-bridge. CUDA needs an NVIDIA driver + libDecoderCUDA; OpenCL needs a GPU ICD + libDecoderOpenCL; macOS needs DecoderMetal in the framework. Force CPU with EXR_CONVERTER_BRAW_CPU=1 to compare.

Official sample clip (from the SDK package, not this repo): profile.braw.

Bridge source location

scripts/build_braw_bridge.py finds the confidential bridge source via BRAW_BRIDGE_SRC, ~/code/braw-sdk-private/bridge, or by downloading the derek-rein/braw-sdk-private tarball at BRAW_BRIDGE_REF (default bridge-v1) using BRAW_SDK_READ_TOKEN / gh auth. Without access, builds skip the bridge and the app reports the format as unavailable.

Source: EXR Converter on GitHub