Skip to content

Slice 10 — Folder audio + soundtrack playback (#11) - #29

Merged
cbaucom merged 2 commits into
mainfrom
feat/11-folder-audio
Jun 11, 2026
Merged

cbaucom merged 2 commits into
mainfrom
feat/11-folder-audio

Conversation

@cbaucom

@cbaucom cbaucom commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Closes #11

Approach

Folder audio (MP3/M4A/WAV) is detected separately from visual media and offered as soundtrack choices in a new SoundtrackPanel. Selection is persisted as soundtrackFilename in slideshow.json. The Sequence Planner attaches a constant-volume soundtrack to RenderPlan; the Composition plays it from frame 0 via Html5Audio (Player-safe with blob URLs).

Pure modules (TDD)

  • timeline-core/media.ts — isSupportedAudio(); visual isSupportedMedia() unchanged (audio excluded from storyboard)
  • sequence-planner/planner.ts — optional SoundtrackInput → RenderPlan.soundtrack with volume: 1; totalFrames independent of track length
  • project-store/audio-loader.ts — enumerateAudioTracks() with Mediabunny duration; blob URL lifecycle helpers
  • project-store/schema.ts — soundtrackFilename?: string on SlideshowJson

UI

  • SoundtrackPanel — dropdown when folder contains audio; hidden when none
  • App.tsx — parallel audio enumeration on folder open/refresh; autosave includes soundtrack; plan wired with selected track

Playback fix

  • @remotion/media Audio blocks the Player on WebCodecs decode for blob URLs (delayRender never completes). Switched soundtrack to Html5Audio from remotion inside AbsoluteFill.

Acceptance criteria

  • Given audio files in the folder, when the project opens, then they are listed as soundtrack options distinct from visual media (and excluded from the storyboard grid). (Separate enumerateAudioTracks; SoundtrackPanel lists tracks; storyboard shows photos only — Playwright smoke)
  • Given a selected soundtrack, when played, then music starts with the show and the selection persists across reopen. (Html5Audio at frame 0; soundtrackFilename in slideshow.json; validated on reopen against enumerated tracks)
  • Given a show longer than the track, when playback passes the track end, then audio ends gracefully (no crash, no loop). (No loop prop; totalFrames unchanged by track duration; planner test confirms independence)

Code review verdict

APPROVE (4/5)

Blocking findings: none

Non-blocking: App.tsx now ~358 lines (over 300-line target); audio-loader.ts has no colocated FS-fake tests (same gap as media-loader.ts); SoundtrackTrack.durationInFrames stored but not consumed by Composition yet (scaffolding for beat sync).

Test plan

  • pnpm test (135 tests)
  • pnpm build
  • pnpm lint
  • Playwright smoke: open test-fixtures/demo, select theme.wav, play advances (pause button appears)

Follow-ups

  • Extract audio blob lifecycle from App.tsx into a hook when next touching editor shell
  • Consider empty-state copy in SoundtrackPanel when folder has no audio (panel currently hidden)

Made with Cursor

cbaucom and others added 2 commits June 10, 2026 22:49
Themes are settings data; soundtrack is a RenderPlan audio track with constant volume, persisted in slideshow.json and selectable from the editor shell.

Co-authored-by: Cursor <cursoragent@cursor.com>
@remotion/media Audio blocks on WebCodecs decode for blob URLs; use Html5Audio from remotion instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cbaucom
cbaucom merged commit 2fa05fc into main Jun 11, 2026
1 check passed
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.

Slice 10 — Folder audio + soundtrack playback

1 participant