AI-assisted project. This codebase was created with Claude (Anthropic), directed and reviewed by a human author. The OFX host, parameter mapping and pixel path are checked against real OFX plugins by automated harnesses in this repo, including a headless OpenGL test that drives a generated plugin the way a host would (see docs/03-verification.md). I've run generated bundles inside Resolume on a Mac, on real content (v0.5.1, August 2026), but it's never been used on a live show. Treat it as a working prototype rather than production tooling.
Run OpenFX plugins (the format DaVinci Resolve uses) inside Resolume Arena/Avenue as native FFGL effects.
A standalone generator scans your OFX plugin folders and makes one FFGL bundle per plugin, each showing that plugin's real parameters, with their real names, units, ranges and groupings, in Resolume's own UI. No fixed pool of anonymous 0–1 sliders.
Any plugin format, any host. Every command in that video really ran. The original 33-second video shows the generator app doing the OpenFX → Resolume direction.
A 33-second tour of the real app, driven through its own controls. The plugins it converts are the OpenFX examples built from source; nothing was installed into a real Resolume folder to film it.
v0.10.0 — prebuilt for macOS and Windows. Pick your platform:
macOS — Universal (Apple Silicon + Intel)
| Build | Download | Size |
|---|---|---|
| Universal (Apple Silicon + Intel) · .zip archive (OpenFX — Resolve, Vegas, Nuke) | resolume-ofx-bridge-macos-universal.zip |
6.1 MB |
Windows — x64
| Build | Download | Size |
|---|---|---|
| x64 · .zip archive (OpenFX — Resolve, Vegas, Nuke) | resolume-ofx-bridge-windows-x86_64.zip |
3.1 MB |
All builds, checksums and release notes: github.com/stoatworks-labs/resolume-ofx-bridge/releases.
macOS builds are signed and notarised and open normally. The Windows builds are unsigned, so SmartScreen warns once.
ofx-bridge.stoatworks-labs.com: nothing to install, and nothing gets uploaded. Because the shells describe their own guest when the host loads them, assembling a wrapped plugin is just a file copy, so a web page can do it: pick the FFGL or After Effects bundle, pick an output folder, done.
It can't do everything this build does. It never runs your plugin, so it can't tell you
why one won't wrap; it's Chrome or Edge on a desktop only; the Windows and Linux shells
it hands out have never rendered a frame; and macOS quarantines anything a browser writes,
so you'll need one xattr -dr before the plugin will load. The page tells you all that as
well.
Resolve's Fusion page reports the frame rate on the effect but not on its clips. The shell used to read the output clip's rate, which Fusion leaves out, so a wrapped FFGL or After Effects plugin failed every render there. It now asks the output clip, the source clip and then the effect, so in Fusion the guest's clock runs at the timeline's own rate (checked at 24 and 25 fps); it only assumes 24 fps, Resolve's default timeline rate, where a host reports no rate at all. Every wrapped bundle carries its own copy of the shell, so a plugin wrapped before this fix has to be wrapped again to get it.
Real output from the OpenFX Invert example, rendered through the generated FFGL
plugin in an OpenGL context, before on the left and after on the right:
The same for the Gain example at scale = 1.8. Note the grey wedge along the
bottom clipping to white about halfway across, which is what a 1.8× gain should
do:
And the same again from a plugin rendering entirely on the GPU with Metal, pixel-equivalent to the CPU result at 5.4× the speed:
Neither image is a mock-up: both are written by
ffgltest --demo straight out of the plugin's
framebuffer.
The obvious design is a single "OFX Host" effect with a dropdown listing your installed plugins. FFGL can't express that.
FFGL 2.2 can change a parameter's display name, visibility and dropdown elements at runtime. But its header explicitly lists range and default-value change events as not supported, and a parameter's type is fixed when the plugin loads. So a dropdown wrapper would have to declare a fixed pool of pre-typed 0–1 sliders and rename them, with every parameter losing its real units, and any plugin with more parameters of a type than the pool has slots couldn't be shown at all.
Generating one bundle per plugin keeps each parameter just as its author declared it. See docs/01-architecture.md.
You don't need a compiler. Each generated bundle is a copy of one prebuilt binary plus a JSON manifest, which the plugin reads when the host loads it.
Download the release, unzip, and open OFX Bridge.app: choose a folder of OFX
plugins (or a single .ofx.bundle), choose where to install, press Start.
On Windows there's no app. ofxgen.exe does everything it does, and the
command-line section below is the whole story.
The Add to buttons fill the destination in for whichever Resolume products
are installed. Only Arena and Avenue are known to scan an Extra Effects
folder. Buttons appear for Alley and Wire because that's where they'd look if
support arrives, and clicking one says as much in the log.
The app clears macOS quarantine from what it writes, which matters because Resolume silently skips a quarantined plugin rather than asking.
./ofxgen generate --out ~/Documents/Resolume\ Arena/Extra\ EffectsThat scans the conventional OFX locations for your platform (plus anything on
OFX_PLUGIN_PATH) and writes one FFGL bundle per usable plugin. Add --dir to
scan somewhere else:
./ofxgen generate --dir /path/to/my/plugins --out ~/Documents/Resolume\ Arena/Extra\ Effects--bundle /path/to/one.ofx.bundle generates from a single plugin instead.
Then rescan effects in Resolume.
Both the app and the CLI strip com.apple.quarantine from what they write. If
plugins still don't appear after something else has copied them around, clear
it by hand:
xattr -dr com.apple.quarantine ~/Documents/Resolume\ Arena/Extra\ Effectsgit clone --recursive https://github.com/stoatworks-labs/resolume-ofx-bridge
cd resolume-ofx-bridge
cmake -S . -B build && cmake --build build -j8There's probably no OFX plugin on your machine even if you have Resolve.
Resolve compiles its own ResolveFX into the application rather than installing
loadable bundles, so /Library/OFX/Plugins is usually empty. Build a test corpus
from the OpenFX examples:
./scripts/build-test-plugins.shInspect what they contain:
./build/ofxprobe --dir build/test-pluginsuk.co.thefoundry.BasicGainPlugin
label : OFX Gain Example
contexts : OfxImageEffectContextFilter OfxImageEffectContextGeneral
parameters : 8
scale OfxParamTypeDouble scale (0..100)
scaleComponents OfxParamTypeBoolean Scale Individual Components
componentScales OfxParamTypeGroup Components
scaleR OfxParamTypeDouble red (0..100)
...
Generate FFGL bundles from them, and check one loads correctly:
./build/ofxgen generate --dir build/test-plugins --out build/generated
./build/ofxgen verify build/generated/OFX_Gain_Example.bundleunique ID : TMvU
name : OFX Gain Example
type : effect
parameters: 6
scale standard default=1 range=0..100
scaleComponents boolean default=0 range=0..1
scaleR standard default=1 range=0..100 group=Components
scaleG standard default=1 range=0..100 group=Components
scaleB standard default=1 range=0..100 group=Components
scaleA standard default=1 range=0..100 group=Components
Eight OFX parameters become six FFGL ones: the group and page carry no value of their own, the group becomes a heading on its children instead, and the 0–100 ranges survive intact.
OFX Bridge.app |
the same generation with a window around it: pick, press Start, watch the log |
ofxgen generate |
scan for OFX plugins and write FFGL bundles |
ofxgen list |
show what was found, and why anything was skipped |
ofxgen verify |
load a generated bundle as a host would and print what it advertises |
ofxprobe |
dump a plugin's parameters; --render pushes a frame through it on the CPU |
ffgltest |
drive a generated bundle through a real OpenGL context; --bench to time it |
- Only the Filter context is hosted, since that's what maps onto an effect slot in a Resolume clip. Generator, Transition and General-only plugins are reported and skipped.
- GPU rendering via Metal or OpenGL; CPU otherwise. A plugin advertising OFX Metal render (what Resolve-targeted plugins on macOS use) renders on the GPU with no CPU round trip, 5.4× faster at 1080p and 3.6× at 4K. OFX OpenGL render is supported too. Everything else takes the CPU path, a full GPU → CPU → GPU trip per frame. See docs/04-gpu-acceleration.md.
- OpenCL is implemented and verified (4.2× faster than CPU at 1080p), though Metal wins when a plugin offers both.
- The Metal and OpenCL interops are macOS. A Windows build advertises neither, so plugins offering them are declined when they describe themselves rather than failing part-way through a frame; OFX OpenGL render and the CPU path work there as they do on macOS. What's verified on which platform is in docs/03-verification.md.
- CUDA is written but has never been compiled or run: it needs an NVIDIA GPU, which macOS hasn't supported since 10.13. The host doesn't advertise CUDA support, so such plugins are declined cleanly rather than failing mid-render. See docs/04-gpu-acceleration.md.
- OpenGL-render plugins must use core-profile GL to work in Resolume. Immediate-mode drawing is illegal in a core profile and macOS has no compatibility profile above 2.1.
- Licensed plugins will mostly refuse to load. The bridge tells plugins the truth about which host it is, and many commercial OFX plugins only license themselves to hosts they recognise. That's the vendor's decision, and I don't work around it here.
- Parametric (curve) parameters are declined: FFGL has no equivalent, and any flattening would misrepresent the plugin's UI.
- Several wrapped plugins in one host need bundles made after v0.9.3. Every wrapped plugin carries its own copy of the bridge's binary, and until this fix the copies exported symbols a host could share between them. With two FFGL plugins wrapped for OpenFX on its plugin path, DaVinci Resolve aborted at startup. Bundles generated for Resolume had the same flaw: in a host that loads plugins into one global namespace, every one of them would run the first one's effect. Wrap or generate again to pick up the fix.
- docs/01-architecture.md: why a generator, and how a copied binary knows which plugin it is
- docs/02-parameter-mapping.md: how each OFX parameter type becomes FFGL parameters
- docs/03-verification.md: what is actually tested, and what isn't
- docs/04-gpu-acceleration.md: where a frame actually goes, and which GPU paths exist
- docs/06-ofxprobe.md:
ofxprobeas a command-line OpenFX test host: sequences, time, contexts, keyframes,--quirks fusion - AGENTS.md: onboarding, invariants and the traps found along the way
This project is built on other people's work — see ATTRIBUTIONS.md.
MIT — see LICENSE.
Bundles OpenFX (BSD-3-Clause) and the Resolume FFGL SDK as submodules; each retains its own licence.



