Skip to content

Export runs up to one frame per span longer than its timeline #1162

Closed

Description

@EtienneLescot

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: duration reads 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 k at programme time k / 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

  1. added
    status: fixed in mainWork is merged into main but may not be in a downloadable release yet.
    status: pending releaseMerged change is waiting for a packaged desktop release.
    on Oct 13, 2026
  2. added this to the Next Release milestone on Oct 13, 2026
  3. github-actions commented on Oct 13, 2026

    @github-actions
    Contributor

    Fixed by #1163 and merged into main.

    This change is assigned to the Next Release release milestone and is not necessarily available in the latest downloadable desktop release yet. It is currently marked as status: pending release until a packaged release containing it is published.

  4. EtienneLescot commented on Oct 15, 2026

    @EtienneLescot
    CollaboratorAuthor

    Moved into v2.1.0 as part of the pre-release cut.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: fixed in mainWork is merged into main but may not be in a downloadable release yet.status: pending releaseMerged change is waiting for a packaged desktop release.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions