Repository navigation
fix(engine): a render no longer decodes the videos it replaces with extracted frames - #6142
Conversation
Edit accuracy: accurate 271 (base branch 271), smooth 128 of thoseThe gate passes. Quarantined, measured but not gated (0) Unstable (2)
|
0e11989 to
c2d1e76
Compare
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · head f387a354
The hold and isRenderFrameVideo look a video up by el.id. skipReadinessVideoIds holds render ids (data-hf-render-id, see core/src/compiler/mediaRenderIds.ts). When an id appears in two scenes, the second element is clip__hf2, but both elements still have id="clip". So an element that isn't replaced can be held at preload=none and render blank. ↓ inline
Scope
Read all 7 files. Traced where the skip list comes from (collectVideoReadinessSkipIds, renderChunk.ts:684) and how ids are bridged (mediaRenderIdBridge.ts). The existing pollVideosReady filter also keys on v.id. That's pre-existing, and its only effect there was not waiting on a video. CI was still running at review time.
f387a35 to
f93bad6
Compare
a78d3f7 to
6f52a79
Compare
…acted frames Two scenes can share a video id. The render id tells them apart, so a live video is no longer held.
6f52a79 to
b4823b8
Compare
What
A render no longer starts a video decoder for each video it replaces with extracted frames. A film cut into 163 pieces from one 1080p source renders in 1.4 GB of Chrome memory instead of 6.9 GB, with identical output.
Why
For a video the renderer replaces with frames extracted by ffmpeg, the page's own decoder never supplies a pixel; the renderer already skips waiting for these videos (
skipReadinessVideoIds). But the page still decoded every one: Chrome starts a parsed<video>at its default preload, and the runtime then forcedpreload="auto"andload()on each (preloadMedia, and the per-tick promotion insyncRuntimeMedia). Chrome keeps one decoder per element, so memory grows with the number of clips, not the number of distinct sources.Measured on the devbox, one worker, 1280x720 output from one 1080p source, whole process tree sampled every 0.5 s (peak RSS):
preload="none"authored; default attributes behave as the 163 case)About 34 MB per extra clip on main, none with the fix. The 163-clip output is the same 490 frames with the same per-frame hash before and after.
Related work
Preview already loads only media near the playhead (#4682, #5716); this is the render-side equivalent. Preview is untouched: the new behaviour needs
__HF_RENDER_FRAME_VIDEO_IDS, which only a render sets.How
engine(renderFrameVideoHold.ts,frameCapture.ts): before any page script, the render hands the page the ids of the videos it replaces and aMutationObserverholds each atpreload="none"the moment it is parsed (also for sub-compositions that add them later). It has to be at parse time: Chrome ignores anoneset once the fetch has started.coreruntime (preloadMedia.ts,media.ts):preloadMediaand the per-tick preload promotion leave those videos alone. One predicate,isRenderFrameVideo, owns the rule.Videos the render does not replace (extraction failed, or not extracted) are not in the list and load as before, so readiness waits and native decoding are unchanged for them.
Test plan
preloadMedia.test.ts(a render-frame video is neither preloaded nor loaded; other videos and audio with the same id still are),media.test.ts(the per-tick sync keeps it at none), and the real-ChromerenderFrameVideoHold.browser.test.ts(listed ids parse atnoneat the top level, nested, and when added later; the unlisted one staysmetadata). All fail against a no-op/old version and pass; core runtime 2342/2342 and the browser file 2/2, three runs in a row.frameCapturesuites 300/300;tsc --noEmitclean in core and engine;oxfmtandoxlintclean.