Skip to content

[Bug]: Reordering clips rewrites imported audio tracks (bed stretched over another clip, loop pushed past the end) #1011

Description

@EtienneLescot

What happens

Reordering clips under imported audio does not carry the audio with its clip: the tracks are rebuilt, and the result is stored (autosave), so it survives a restart once the undo history is gone.

Measured on v2.0.0 (macOS), 3 clips — b6cdac 0–102.1 s, 63fedd 102.1–163.97 s, d51b65 163.97–266.07 s — with a 30 s music bed across the b6cdac/63fedd junction and a looping 4 s track across 63fedd/d51b65 (both kind: music):

before after moving 63fedd to the end
bed fragments b6cdac 89.869–102.1 s, 63fedd 102.1–119.869 s b6cdac 89.869–102.1 s, d51b65 102.1–204.2 s (offset 12231), 63fedd 204.2–221.969 s (offset 114331)
loop fragments 63fedd 119.869–163.97 s, d51b65 163.97–199.977 s 221.969–324.069 s and 324.069–385.939 s — entirely past the 266.07 s programme end

The 30 s bed now spans 132 s and covers a clip it never touched; the loop is pushed out of the film. Moving the clip back makes it worse (bed 89.869–266.07 s, loop 266.07–430.04 s). Only Ctrl+Z restores it.

Cause

mapAllRegionCollections (src/lib/ai-edition/document/timeline.ts:396) runs every structural clip edit's audio through separateAudioLanes(reanchorAudioTracks(fn(audioTracks), …)):

  1. fn — here rederiveAnchoredRegion via withClipsChanged → rederiveRegionMs — moves each anchored fragment with its own clip. After a reorder that is correct, but the fragments of one track are no longer adjacent on the ruler (bed: 89.869–102.1 s and 204.2–221.969 s).
  2. reanchorAudioTracks → collapseTracksToPills (audioTracks.ts:132) folds each trackId back into ONE span from the first fragment's startMs to the last fragment's endMs (89.869–221.969 s). That assumes the fragments are contiguous; after a reorder the span swallows whatever clip now sits between them.
  3. anchorAudioTrackFragments re-ventilates that inflated span over the new layout, so the clip in the middle gets a full-length fragment, and offsetMs keeps advancing by elapsed span (12231 → 114331), pointing past the end of a 30 s file.
  4. separateAudioLanes (audioTracks.ts:463) then sees the inflated bed overlapping the loop (same music row) and shifts the whole loop pill to the bed's end — past the programme end. It shifts startMs/endMs only, so the shifted fragments no longer agree with their own clipId/sourceStartSec anchors.

Every number in the table follows from these four steps. The reanchor pass was added in 521d0bd (in v1.11.0) to repair offsetMs after re-ventilation, which copies it verbatim. A move/reorder never re-ventilates — rederiveAnchoredRegion keeps each fragment's own offsetMs, which already encodes its file position — so for these ops the pass is unnecessary and destructive.

Possible fix

  • Only re-run reanchorAudioTracks on fragments that were actually re-ventilated (orphans / never-anchored), not on anchored fragments whose clip survived; or
  • collapse per run of fragments that still meet on the ruler with continuous offsetMs (the existing takesJoin test), instead of per trackId; and
  • have separateAudioLanes move anchors with the ms, or resolve overlap without detaching fragments from their clips.

No test covers moveClip with audio tracks (timeline.test.ts, insertion.test.ts), which is how this got through.

Expected

Each audio fragment travels with the clip it was placed over (checklist "Imported audio and voice-over": "Reorder the clips underneath a track and confirm the track follows the clip it was placed over"), keeps its length and offsetMs, and no clip gains audio it never had.

Steps

  1. Make a project with 3 clips (e.g. drag the same recording to the timeline three times).
  2. Import an audio file (M) across the clip 1/clip 2 junction; import a second one across clip 2/clip 3 and turn Loop on.
  3. Drag clip 2 to the end.
  4. The first track now covers all of the old clip 3; the second is pushed past the end of the timeline. Inspect audioTracks in the project file to see the spans.

Environment

v2.0.0 (DMG, notarized), macOS 27.0, Mac mini M1. main has no app changes since v2.0.0. Found in the v2.0.0 computer-use E2E pass (checklist line 376).

Activity

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

    bugSomething isn't workingstatus: 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