Skip to content

fix: multi-file timeline drop spacing#487

Merged
miguel-heygen merged 1 commit intomainfrom
codex/fix-studio-multi-asset-spacing
Apr 25, 2026
Merged

fix: multi-file timeline drop spacing#487
miguel-heygen merged 1 commit intomainfrom
codex/fix-studio-multi-asset-spacing

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen commented Apr 25, 2026

Problem

Studio could still produce a bad timeline layout when multiple media files were dropped onto the timeline at once.

The files uploaded correctly, but the placement logic treated the group too loosely:

  • MP4 / MOV / MP3 files could be inserted with the same drop start instead of being spaced by their actual media durations
  • dropping onto a row that already contained a long clip could leave the first new media clip overlapping existing content on that same track
  • if duration metadata was unavailable during group placement, the helper could treat a clip as zero-length even though insertion would later write a positive fallback duration
  • the saved HTML could therefore look valid at a glance while still creating track collisions during preview / static guard checks

What this fixes

Multi-file timeline placement

  • resolves each uploaded file's media duration before placing the dropped group
  • places the group sequentially from the drop point instead of assigning every file the same start time
  • falls back to a finite placement duration when duration metadata is unavailable, keeping placement math aligned with the insert fallback path
  • reuses the resolved duration when writing the inserted clip HTML, so the saved data-duration matches the placement math when metadata is available
  • keeps the whole dropped group on one clear row so the assets read as a sequence instead of scattering across rows

Occupied-row handling

  • keeps the requested drop track when the time range is clear
  • if the requested row is already occupied at that time range, moves the whole group to a new clear track below the current timeline rows
  • covers the default { start: 0, track: 0 } placement path when track 0 is already occupied
  • preserves the existing track / z-index update path so older clips keep rendering predictably after the new clips are inserted

Media coverage

  • keeps MP4 and MOV handled as video assets
  • keeps MP3 handled as audio
  • adds regression coverage for MOV / MP3 detection, occupied-row fallback, empty drops, clear high-track drops, and mixed positive / missing durations

Root cause

The multi-file drop helper only knew about the number of uploaded files. It did not know the duration of each uploaded media asset, so it could not build a non-overlapping sequence from the drop point.

The direct file-drop handler also passed placement into each insert independently. That meant the drop could use the same start time repeatedly, and it could target a row that was already occupied by an existing clip.

A smaller edge case existed when a duration resolved to 0 or was otherwise unavailable: placement math did not advance nextStart, but the insert path could still write a positive fallback duration later. The helper now uses a finite fallback for placement too.

Behavior

  • dropping a single file still places that file at the dropped time / track when the row is clear
  • dropping multiple files now creates a sequential group from the dropped time
  • if a file's duration is unavailable during placement, the next file is still spaced forward by a finite fallback
  • if the dropped row is occupied, the group moves together to the next clear track
  • video and audio durations come from metadata when available, with the existing fallback duration still used when metadata cannot be read quickly
  • inserted clips are still persisted into source HTML and the preview refreshes after the drop

Verification

Local checks

  • bun run --filter @hyperframes/studio test -- src/utils/timelineAssetDrop.test.ts -> 12 tests pass
  • bun run --filter @hyperframes/studio test -> 221 tests pass
  • bun run --filter @hyperframes/studio typecheck
  • bunx oxlint packages/studio/src/utils/timelineAssetDrop.ts packages/studio/src/utils/timelineAssetDrop.test.ts
  • bunx oxfmt --check packages/studio/src/utils/timelineAssetDrop.ts packages/studio/src/utils/timelineAssetDrop.test.ts
  • bun run --filter @hyperframes/studio build
  • git diff --check
  • pre-commit hook: lint / format / typecheck

Browser / live verification

Verified against a live local Studio fixture with real media files:

  • dropped a group containing MP4, MOV, and MP3 files onto the timeline
  • confirmed the saved HTML sequenced them at 2.18s, 3.38s, and 4.98s
  • confirmed the existing background clip stayed on track 0 while the new media group moved together to clear track 1
  • confirmed agent-browser errors was clean after the drop
  • captured an agent-browser recording pass for the tested flow

Notes

  • the timeline-multi-drop-repro Studio project and generated MP4 / MOV / MP3 files used for browser verification are local-only and are not part of this PR
  • this PR is intentionally scoped to multi-file drop placement; it does not add broader timeline editing modes or change drag/move behavior for existing clips

@miguel-heygen miguel-heygen force-pushed the codex/fix-studio-multi-asset-spacing branch from 5e055d7 to 7d0a945 Compare April 25, 2026 03:42
@miguel-heygen miguel-heygen changed the title [codex] Fix multi-file timeline drop spacing fix: multi-file timeline drop spacing Apr 25, 2026
@miguel-heygen miguel-heygen marked this pull request as ready for review April 25, 2026 04:01
@miguel-heygen miguel-heygen force-pushed the codex/fix-studio-multi-asset-spacing branch from 7d0a945 to b4ac293 Compare April 25, 2026 04:12
Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-file drop placement looks good after the b4ac293 follow-up. All edge cases I flagged are closed:

  • Zero/missing-duration silent overlap → fixed via FALLBACK_TIMELINE_FILE_DROP_DURATION = 5. Placement math now always advances; the new "uses fallback spacing when a duration is unavailable" test pins the behavior.
  • Default-track at-time-0 occupied → covered by the new "moves a default-track drop to a clear row" test.
  • Empty drop set → covered.
  • Clear high-track placement → covered.

Verified locally on b4ac293:

  • bun test packages/studio/src/utils/timelineAssetDrop.test.ts → 12/12 pass
  • bun run --filter @hyperframes/studio test → 221/221 pass
  • Studio typecheck clean

Sequenced placement with same-track overlap detection is the right model for "user dropped these as a group." The clamp-to-positive on clip.start / clip.duration, and 2dp rounding match the rest of the timeline math. Effect dependency on [activeCompPath, handleTimelineAssetDrop, timelineElements, uploadProjectFiles] is correct for the new closure.

Low blast radius — Studio drag-drop only, no render-pipeline impact.

— Rames Jusso

@miguel-heygen miguel-heygen merged commit 5e1db03 into main Apr 25, 2026
27 of 36 checks passed
@miguel-heygen miguel-heygen deleted the codex/fix-studio-multi-asset-spacing branch April 25, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants