Repository navigation
Export runs up to one frame per span longer than its timeline #1162
Description
Summary
An export runs longer than its timeline: every span (a stretch of one clip at one speed, between trims, regions and clip junctions) rounds its own frame count up, so the error grows with the number of spans, up to one frame per span.
Found in the v2.1.0 RC QA: a two-clip MP4 export (30 fps) ran 2451 frames where the arithmetic gives 2444.9.
Cause
push_speed_segment (crates/compositor/src/regions.rs) gives each span ceil((duration − 1 ms) / speed × fps) frames, and walk_composited_timeline restarts its sampling at each span's start. outputFrameCount.ts mirrors the same arithmetic, so the progress total carries the same error.
Evidence
QA project: 2 clips, 6 trims, a 1.5x and a 4x region per clip, so 14 spans.
- Programme length: 2444.86 frames.
- Sum of per-span ceilings: 2452, which is the UI's total.
- The export holds 2451 packets. Its clip ends are clamped to the screen stream's real length, 48.765 s, against a declared 48.789 s (the audio track's). Per-span ceilings over the clamped windows also give exactly 2451.
Headless repro: CLI export with the installed RC, a 20 s synthetic source, 60 fps.
| Project | Programme frames | Exported (packets) |
|---|---|---|
| one trim | 1079.4 | 1080 |
| one 1.5x region | 1119.8 | 1121 |
| 12 trims | 976.8 | 984 |
Not defects:
- Audio: it always lasts exactly frames ÷ fps.
- Video duration:
durationreads one frame short (81.667 s against 81.700 s) because the muxer records the last frame's timestamp, so the two tracks are in sync.
Fix
- Put the whole timeline on one frame grid: frame
kat programme timek / fps, with programme time carried across spans, trims and clips. - Each span emits the grid frames inside it, and samples the source where the grid puts them.
- The total becomes
⌈(P − 1 ms) × fps⌉for P programme seconds, within one frame of the arithmetic whatever the span count. - Audio follows, because it is stretched to each span's frame count.
Not fixed
The progress total still uses the declared clip length, so it is one frame high when a source's video is shorter than its container. That limitation is documented in outputFrameCount.ts.
Activity
fix(export): put the whole timeline on one frame grid
github-actions commentedon Oct 13, 2026
Fixed by #1163 and merged into
main.This change is assigned to the
Next Releaserelease milestone and is not necessarily available in the latest downloadable desktop release yet. It is currently marked asstatus: pending releaseuntil a packaged release containing it is published.EtienneLescot commentedon Oct 15, 2026
Moved into
v2.1.0as part of the pre-release cut.