You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The "secondary artefacts emitted during render" gap (High/M) from the re-scored Remotion differential. Investigated alongside #178 and refused, with the reasoning recorded here.
What is missing
grep -rn "artifacts" crates/rustmotion-core/src/schema/scenario.rs returns nothing. still and captions are independent subcommands invoked separately from the video render, so producing a thumbnail and a subtitle file next to a video takes three invocations that re-render or re-decode the same content.
Three independent blockers
Each is sufficient on its own; all were found by reading the code.
1. ResolvedScenario has exactly one construction site, and it is not where you would add the field.
ResolvedScenario — the type render, still, info and batch actually consume — is built only at crates/rustmotion/src/include.rs:76-82; every path through loader.rs goes through include::resolve_includes. A field added to Scenario in schema/scenario.rs therefore stays invisible to render.rs unless include.rs is touched too. And crates/rustmotion-studio/src/scenario/model.rs:89 (empty_scenario()) would stop compiling regardless.
2. "Do not re-render" is architecturally blocked, which is the whole point of the feature.
Per-frame RGBA buffers only materialise inside the per-format encode loops — h264.rs:244 inside a rayon::par_iter closure, and the same shape in ffmpeg.rs and formats.rs. render_frame_task(...) is called there, converted to YUV and dropped immediately. Nothing hands a finished frame to a general-purpose hook.
The only function able to produce an arbitrary frame outside those loops is render_frame_task_scaled, which is the render. Calling it a second time for a thumbnail reproduces exactly the cost of the separate rustmotion still invocation the feature exists to replace — so a naive implementation would deliver the syntax without the benefit.
3. Captions cannot be reused cleanly as they stand.
cmd_captions shells whisper.cpp (absent from the environment this was investigated in, so unverifiable there) and writes its output with a bare std::fs::write at captions.rs:422 — not atomic, contradicting the discipline PR #145 (helper commands must not destroy files they do not own) and PR #151 (write to a sibling, promote on success) established.
The honest path, for later
Extract the thumbnail from the already-produced video file, with ffmpeg -ss <t> -i output.mp4, after the encode finishes. Zero additional Skia work, and it reuses the sub-process pattern already in assets.rs. It sidesteps blocker 2 entirely.
That does not help until blocker 1 is resolved: the declaration still has to reach render.rs, which means include.rs and the studio's empty_scenario() move together with schema/scenario.rs.
Captions would need captions.rs's write made atomic first — worth doing on its own merits regardless of this gap.
Open questions for whoever picks this up
Should a failed artefact fail the video, or be reported and skipped? The render is the expensive part; losing it because a thumbnail could not be written seems wrong, but silently producing fewer outputs than declared is the failure mode this repository keeps eliminating.
The "secondary artefacts emitted during render" gap (High/M) from the re-scored Remotion differential. Investigated alongside #178 and refused, with the reasoning recorded here.
What is missing
grep -rn "artifacts" crates/rustmotion-core/src/schema/scenario.rsreturns nothing.stillandcaptionsare independent subcommands invoked separately from the video render, so producing a thumbnail and a subtitle file next to a video takes three invocations that re-render or re-decode the same content.Three independent blockers
Each is sufficient on its own; all were found by reading the code.
1.
ResolvedScenariohas exactly one construction site, and it is not where you would add the field.ResolvedScenario— the typerender,still,infoandbatchactually consume — is built only atcrates/rustmotion/src/include.rs:76-82; every path throughloader.rsgoes throughinclude::resolve_includes. A field added toScenarioinschema/scenario.rstherefore stays invisible torender.rsunlessinclude.rsis touched too. Andcrates/rustmotion-studio/src/scenario/model.rs:89(empty_scenario()) would stop compiling regardless.2. "Do not re-render" is architecturally blocked, which is the whole point of the feature.
Per-frame RGBA buffers only materialise inside the per-format encode loops —
h264.rs:244inside arayon::par_iterclosure, and the same shape inffmpeg.rsandformats.rs.render_frame_task(...)is called there, converted to YUV and dropped immediately. Nothing hands a finished frame to a general-purpose hook.The only function able to produce an arbitrary frame outside those loops is
render_frame_task_scaled, which is the render. Calling it a second time for a thumbnail reproduces exactly the cost of the separaterustmotion stillinvocation the feature exists to replace — so a naive implementation would deliver the syntax without the benefit.3. Captions cannot be reused cleanly as they stand.
cmd_captionsshellswhisper.cpp(absent from the environment this was investigated in, so unverifiable there) and writes its output with a barestd::fs::writeatcaptions.rs:422— not atomic, contradicting the discipline PR #145 (helper commands must not destroy files they do not own) and PR #151 (write to a sibling, promote on success) established.The honest path, for later
Extract the thumbnail from the already-produced video file, with
ffmpeg -ss <t> -i output.mp4, after the encode finishes. Zero additional Skia work, and it reuses the sub-process pattern already inassets.rs. It sidesteps blocker 2 entirely.That does not help until blocker 1 is resolved: the declaration still has to reach
render.rs, which meansinclude.rsand the studio'sempty_scenario()move together withschema/scenario.rs.Captions would need
captions.rs's write made atomic first — worth doing on its own merits regardless of this gap.Open questions for whoever picks this up
--fix's refusal rules and PR fix(cli): stop the helper commands destroying files they do not own #145's file-ownership guards are the precedent to follow.