ADR-0690: VMAFX Binary and AI Tool Aliases¶
- Status: Accepted
- Date: 2026-05-28
- Deciders: Lusoris, Claude (Anthropic)
- Tags: vmafx, rebrand, cli, build, ai, mcp
Context¶
ADR-0686 (VMAFX rebrand umbrella) locked the decision to introduce a vmafx binary that applies modernized defaults: --precision=max (IEEE-754 lossless output, %.17g), auto-backend detection (CUDA > Vulkan > SYCL > CPU — already the CLI default since ADR-0498), and a distinct banner that names the active defaults on startup.
Two approaches to the vmafx binary exist: (A) a symlink to the existing vmaf binary that detects its invocation name via argv[0] basename inspection, or (B) a separate vmafx.c that exec()s vmaf with prepended arguments. Option A produces one binary on disk, zero code duplication, and no extra fork/exec overhead. The argv[0] detection pattern is well- established on POSIX systems (e.g., busybox, ffmpeg multi-call).
For the Python tools (vmaf-train, vmaf-tune, vmaf-mcp), the cleanest alias mechanism is a second [project.scripts] entry pointing to the same callable. pip/hatch installs both entry-point scripts at package install time; the scripts are byte-identical thin wrappers; no import-side detection is required because the Python tools have no session-startup banner that needs to vary.
Decision¶
We apply Option A for the C binary: Meson's install_symlink() installs vmafx → vmaf in bindir; cli_parse.c adds detect_vmafx_mode(argv[0]) which inspects the basename, sets settings->vmafx_mode = true, and after the getopt loop applies precision_max = true / precision_fmt = "%.17g" unless the user passed an explicit --precision flag. The startup banner prints "VMAFX version <V> (precision=max)" in vmafx mode.
For the AI tools we add vmafx-train, vmafx-tune, and vmafx-mcp as additional [project.scripts] entries (pointing to the same callables as the existing vmaf-* entries) in ai/pyproject.toml, tools/vmaf-tune/pyproject.toml, and mcp-server/vmaf-mcp/pyproject.toml.
The existing vmaf, vmaf-train, vmaf-tune, and vmaf-mcp entry points are not changed: this is purely additive.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
| Option A — symlink + argv[0] | One binary; no exec overhead; clean | Slightly non-obvious for maintainers unfamiliar with multi-call patterns | Chosen — minimal on-disk footprint, established pattern |
| Option B — separate vmafx.c exec()s vmaf | Clean separation; no argv[0] logic | Extra fork/exec per invocation; two binaries to maintain; Windows exec() semantics differ | Rejected — overhead not justified when argv[0] detection suffices |
| Option C — vmafx.c with duplicated main() | No runtime detection needed | Full code duplication; two diverging binaries over time | Rejected — maintenance burden unacceptable |
| Python: wrapper scripts in bin/ | Simple shell scripts | Platform-dependent (no native Windows); not pip-installable | Rejected — console_scripts is the idiomatic pip mechanism |
Consequences¶
- Positive:
vmafx --versionshows version + identity;vmafxapplies precision=max by default without extra flags; bothvmaf-*andvmafx-*names work after pip install. - Negative: Maintainers must keep the
vmafx_modebranch incli_parse.cupdated when new defaults are added to vmafx mode. The--versionoutput differs betweenvmaf -vandvmafx -v— CI scripts that parse version strings must accept both prefixes. - Neutral: The
install_symlink()call requires Meson >= 0.61 (already satisfied; the project pins Meson >= 1.0). Downstream packagers who splitvmafandvmafxinto separate packages must install both to the samebindirto keep the symlink valid.
References¶
- ADR-0686: VMAFX rebrand umbrella (parent decision).
- ADR-0119:
--precisionflag and%.17glossless format. - ADR-0498:
--backendexclusive selector and auto-backend default. - req: "Option A (preferred): meson installs vmafx as a symlink to vmaf, then vmaf argv[0]-detects 'vmafx' and applies modernized defaults inline."