Skip to content

feat(studio): render geometry-sized video filmstrips - #4234

Open
miguel-heygen wants to merge 3 commits into
mainfrom
hfoss34/timeline-filmstrip
Open

miguel-heygen wants to merge 3 commits into
mainfrom
hfoss34/timeline-filmstrip

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Video clips request a geometry-sized filmstrip after measurement and keep a one-frame poster tier available during fast scroll. Geometry requests use stable quantized cache identities and one 4K geometry ceiling.

Before

Origin/main, timeline region at Fit with video clips and the Voiceover audio row at rest:

Before, Fit

Origin/main, mid-scroll timeline region with video clips and the Voiceover audio row:

Before, mid-scroll

Origin/main, the same timeline at 4x zoom and the same scroll position as After:

Before, 4x zoom

After

After the change, timeline region at Fit with video clips and the Voiceover audio row:

After, Fit

After the change, timeline region at 4x zoom with video clips and the Voiceover audio row:

After, 4x zoom

The Footage Frame 1 and Footage Frame 2 no preview labels are not an intended 4x behavior. The non-rich one-frame poster lease remains active at every zoom and is the fallback while rich work is unavailable; those rows are failing both poster and rich decoding in this capture and therefore remain an open preview defect, not an expected filmstrip state.

Decode cost

Devbox decode-cost proxy on the 1080x1920 fixture, evenly spaced timestamps across the first 6 seconds, 3 runs: 6 frames averaged 1.67 s; 20 frames averaged 5.47 s, 3.26x. The 500px example needs 5 visible frames but quantizes the rich request to 8, trading a bounded decode step for stable cache identities. Every video clip now enqueues TWO jobs where main enqueued one, against concurrentVideoDecodes: 2; the 1-frame poster is what paints during scroll, and the filmstrip follows once scrolling settles.

Scheduler safety

120 mounted clips do not decode 20 frames each at once. The scheduler limits video work to the concurrency bucket at packages/studio/src/player/lib/thumbnailScheduler.ts:345-348, pauses only rich work while scrolling at packages/studio/src/player/lib/thumbnailScheduler.ts:207-210 and :258-261, and retains results only within byte and entry budgets at packages/studio/src/player/lib/thumbnailScheduler.ts:327-334 and :384-392, configured by packages/studio/src/player/lib/timelineViewportBudgets.ts:70-82. The one-frame poster request is non-rich, so it remains eligible during scrolling. Quantised request counts and the cache byte budget keep a 120-clip timeline from holding 120 x 20 decoded frames.

Validation

  • Focused Studio suites: 26 tests passed for poster deferral, two-tier requests, and thumbnail geometry.
  • Studio typecheck passed after generated core artifacts were built; Oxlint and oxfmt passed on the changed files.
  • The capture script waited for readiness, asserted a non-zero clip count, and asserted the audio control before taking screenshots.
  • The 4K ceiling is Math.ceil(3840 / (66 * (16 / 9))), named once with its geometry reasoning beside the owner budget.

@miguel-heygen
miguel-heygen force-pushed the hfoss34/timeline-filmstrip branch from d4e484a to ed17c41 Compare September 21, 2026 04:06
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