Skip to content

Caller-supplied expression context

We want a filter’s expression parameter to optionally be a PHP closure evaluated per frame — e.g. drawtext’s x driven by host-language logic, not just FFmpeg’s expression mini-language. That’s a design/PRD goal that’s currently deferred.

av_expr already supports caller supplied context: av_expr_parse() takes const_names (variables) and func1_names/funcs1, func2_names/funcs2 — custom function callbacks. So the evaluation engine can already call back into caller code.

The problem is filters parse their expression options internally, with their own fixed variable and function tables. A caller building a graph has no way to add variables or functions to a filter’s expression evaluation — the door av_expr opens is closed at the filter boundary. So there’s no public path to make a host closure participate in, say, drawtext’s x expression without patching the filter.

  1. Per-instance expression context — a way to register extra const_names/funcs on a filter instance that the filter passes through to its av_expr_parse() calls. Builds directly on the callback support av_expr already has; the hard part is the filter-side plumbing and doing it generically rather than per filter.
  2. A documented opt-in for a few high-value filters (drawtext, geq) first, as a proof of concept, before any generic mechanism.

Per our no-private-struct-access decision (ADR 0001) we can ship a custom AVFilter on our fork that bridges expression evaluation to PHP, without reaching into private structs. The upstream path is preferable (no fork divergence, helps every binding) but this proposal isn’t blocking — it’s the better long-term home for the capability.

  • How drawtext/geq wire av_expr_parse() (the func1/func2 and const_names they pass).
  • Whether a generic per-instance context is feasible or whether it’s inherently per-filter.
  • Thread-safety / lifetime of caller callbacks across frames.

Seed / north-star. Depends conceptually on expression variables & constants (you need to know a filter’s existing vars before adding your own).

An Artisan Build project.

Built on FFmpeg — an independent binding, not affiliated with or endorsed by the FFmpeg project. Support FFmpeg.