Skip to content

video-mode: flatten cursorExpression so ffmpeg 8's eval depth cap can't kill long renders - #43

Draft
mmkal wants to merge 3 commits into
mainfrom
video-mode-ffmpeg8-eval-depth
Draft

video-mode: flatten cursorExpression so ffmpeg 8's eval depth cap can't kill long renders#43
mmkal wants to merge 3 commits into
mainfrom
video-mode-ffmpeg8-eval-depth

Conversation

@mmkal

@mmkal mmkal commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Problem

ffmpeg 8 (homebrew's current: 8.0.1) added a recursion-depth cap (~100) to its expression parser. video-mode's pointer overlay builds the cursor's x/y as one nested if(between(t,a,b), value, <rest>) level per cursor waypoint segment — depth O(actions). Any spec with roughly 35+ pointer-highlighted actions now dies at render time:

[Parsed_overlay_351] [Eval] Missing ')' or too many args in 'if(between(t,49.123,49.423),(184+...
Error: Command failed: ffmpeg -hide_banner ... <several kilobytes of -filter_complex> ...

Empirically: nesting depth 90 parses, 100 fails. ffmpeg ≤7 has no limit, which is why short specs and older installs never noticed. First seen rendering iterate's specs/mobile/approvals.spec.ts (~350 filter nodes).

Fix

The waypoint segments are sequential and disjoint, so the nested chain is just a first-match lookup. Flatten it to a constant-depth sum:

Σ (gte(t,aᵢ)*lt(t,bᵢ))·valueᵢ(t)  +  (1 − gte(t,first)·lt(t,last))·base

Half-open windows (instead of inclusive-both-ends between) keep a shared segment boundary from firing two terms and doubling the coordinate; at a boundary the successor term yields the same position the nested version picked. base is the last waypoint's coordinate, matching the old fallback outside all segments. Depth stays ~10 no matter how long the spec gets.

Tests

spec/video-mode-cursor-expression.spec.ts (node-only, 400 segments — 4× the cap):

  • nesting depth stays < 32 at any waypoint count (the cross-version guard: CI's older ffmpeg can't repro the parse failure itself)
  • the installed ffmpeg parses and evaluates the expression through the real overlay quoting (fails on ffmpeg 8 with the old nested form)
  • values match the waypoint smoothstep interpolation at every segment boundary and midpoint — mutation-checked: inclusive windows (the coordinate-doubling trap) fail this test

Verification

Full suite on ffmpeg 8.0.1 (the strict parser): 157 passed, 3 skipped (llm-recover, needs credentials). spec/todo-app.spec.ts rendered baseline:

video-rendered.webm

The originally-failing iterate mobile approvals spec (48s, 100+ waypoint segments), rendered green against this branch's build:

video-rendered.webm

Review notes

Riskiest part: the boundary semantics of the flattened sum (double-fire / gap edge cases) — that's what the value test pins down, boundaries included. The complement term assumes segments are contiguous, which is structural (segments are consecutive waypoint pairs). Review order: src/plugins/video-mode.ts (cursorExpression, one function), then the spec. On merge: rendered output is pixel-identical in intent; only the filter string shape changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WZz4ydAhbRixWwJLpUEnSj

mmkal and others added 2 commits September 1, 2026 14:21
ffmpeg 8 limits expression nesting to ~100; cursorExpression nests one
if() per cursor waypoint segment, so long pointer-mode specs fail at
render with 'Missing )' inside a multi-kilobyte command-line error.
Diagnosis verified against ffmpeg 8.0.1; fix is a constant-depth
sum-of-disjoint-windows rewrite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZz4ydAhbRixWwJLpUEnSj
…eg 8

ffmpeg 8 caps expression nesting at ~100 levels; the old form nested one
if(between(...)) per cursor waypoint segment, so pointer-mode tests with
~35+ highlighted actions failed to render. The flat form sums disjoint
half-open gte/lt window terms plus a complement term carrying the last
waypoint's position, keeping depth constant at any length. New spec
guards depth, ffmpeg parseability under production quoting, and
boundary-exact values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZz4ydAhbRixWwJLpUEnSj
@pkg-pr-new

pkg-pr-new Bot commented Sep 1, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/middlewright@43

commit: f1b0fae

…failing iterate spec

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZz4ydAhbRixWwJLpUEnSj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant