Context
The studies size voice-over beats and soundtracks from the announced duration. Three places compute it, and they disagree.
1. rustmotion info sums scene durations
crates/rustmotion/src/cli/commands/info.rs:15-18 computes total_duration as the sum of scene.duration, and total frames as the sum of round(duration × fps). It ignores legacy transition overlap and the v2 at placement.
| Scenario |
info |
validate |
frames rendered |
v1, two 1.0 s scenes, the second with a 0.6 s iris |
2.0 s (60 frames) |
1.4 s |
42 |
v2, at: 0 and at: 1.0, both 2.0 s |
4.0 s (120 frames) |
3.0 s |
90 |
{"version":"1.0","timing":"v2","video":{"width":320,"height":180,"fps":30,"background":"#000000"},
"composition":[{"type":"slide","scenes":[
{"at":0,"duration":2.0,"children":[]},
{"at":1.0,"duration":2.0,"children":[]}]}]}
Expected: info reports the frame count the render will produce, from the same function the encoder uses.
2. A scene duration that falls on a half frame adds one frame per scene
{"version":"1.0","video":{"width":160,"height":90,"fps":30,"background":"#000000"},
"scenes":[{"duration":1.05,"children":[]},{"duration":1.05,"children":[]}]}
validate announces 2.1 s, which is 63 frames at 30 fps. render writes 64: each scene rounds 31.5 up to 32, and the error accumulates across scenes. The same happens with timing: "v2". With 20 beats of 0.35 s at 30 fps, the video ends 10 frames after the soundtrack.
Expected: scene boundaries are computed as round(cumulative_time × fps), so the total is round(total × fps). Or validate warns when a duration isn't a whole number of frames, which the beat grid of #336 could also snap.
Also relevant: SKILL.md shows rustmotion info scenario.json, which the CLI rejects (filed in the SKILL.md issue).
Found in: 9styles, reel 4
Context
The studies size voice-over beats and soundtracks from the announced duration. Three places compute it, and they disagree.
1.
rustmotion infosums scene durationscrates/rustmotion/src/cli/commands/info.rs:15-18computestotal_durationas the sum ofscene.duration, and total frames as the sum ofround(duration × fps). It ignores legacy transition overlap and the v2atplacement.infovalidateirisat: 0andat: 1.0, both 2.0 s{"version":"1.0","timing":"v2","video":{"width":320,"height":180,"fps":30,"background":"#000000"}, "composition":[{"type":"slide","scenes":[ {"at":0,"duration":2.0,"children":[]}, {"at":1.0,"duration":2.0,"children":[]}]}]}Expected:
inforeports the frame count the render will produce, from the same function the encoder uses.2. A scene duration that falls on a half frame adds one frame per scene
{"version":"1.0","video":{"width":160,"height":90,"fps":30,"background":"#000000"}, "scenes":[{"duration":1.05,"children":[]},{"duration":1.05,"children":[]}]}validateannounces 2.1 s, which is 63 frames at 30 fps.renderwrites 64: each scene rounds 31.5 up to 32, and the error accumulates across scenes. The same happens withtiming: "v2". With 20 beats of 0.35 s at 30 fps, the video ends 10 frames after the soundtrack.Expected: scene boundaries are computed as
round(cumulative_time × fps), so the total isround(total × fps). Orvalidatewarns when a duration isn't a whole number of frames, which the beat grid of #336 could also snap.Also relevant:
SKILL.mdshowsrustmotion info scenario.json, which the CLI rejects (filed in the SKILL.md issue).Found in: 9styles, reel 4