fix: bound waveform extraction memory usage for large video files#1544
Open
smirk-dev wants to merge 1 commit into
Open
fix: bound waveform extraction memory usage for large video files#1544smirk-dev wants to merge 1 commit into
smirk-dev wants to merge 1 commit into
Conversation
Waveform extraction called file.arrayBuffer() on the full uploaded video regardless of size. For uploads up to the 2GB cap this allocated multiple gigabytes (raw buffer + decoded PCM), spiking the heap and crashing browser tabs before editing began. - Add MAX_WAVEFORM_FILE_SIZE_BYTES (300MB) config in src/lib/constants.ts. - Refactor useAudioWaveform to a discriminated status union (idle | loading | ready | disabled | error). Files over the threshold are never read into memory; within the threshold audio is read through a bounded Blob.slice so decodeAudioData never receives more than the threshold's bytes. Small files are unchanged. - Strengthen cancellation: in-flight reads/decodes bail out on unmount or file change before creating an AudioContext or setting state. - Wire WaveformCanvas into TrimControl and render a placeholder + helper text when extraction is disabled for large files. - Add tests for threshold behaviour, the no-full-read guarantee, custom thresholds, decode errors, and unmount cancellation. Closes magic-peach#1013 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@smirk-dev is attempting to deploy a commit to the magic-peach1's projects Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
✅ PR Format Check Passed — @smirk-devBasic format checks passed. A maintainer will review your code changes. This does not mean the PR is approved — it just means the format is correct. |
Contributor
👋 Thanks for your PR, @smirk-dev!Welcome to Reframe — a browser-based video editor built for everyone 🎬 What happens next
Quick checklist
Useful links
Happy coding! 🎉 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Waveform extraction for large videos no longer reads the entire file into memory.
useAudioWaveformpreviously calledfile.arrayBuffer()on the full uploaded video regardless of size; for uploads near the 2 GB cap this allocated multiple gigabytes (raw buffer + decoded PCM + processing buffers) and crashed browser tabs before editing even began. Extraction is now bounded by a configurable size threshold, with a graceful placeholder for files above it.Closes #1013
Technical details
File-size threshold
MAX_WAVEFORM_FILE_SIZE_BYTES(default 300 MB) insrc/lib/constants.ts, overridable per call via a thirduseAudioWaveformargument.Bounded / sliced decode strategy
file.slice(0, maxFileSizeBytes).arrayBuffer()instead offile.arrayBuffer()on the whole file. For inputs within the threshold this is the entire file (unchanged behaviour); the slice caps the worst-case allocation sodecodeAudioDatanever receives more than the threshold's worth of bytes.file.slice/arrayBufferare never invoked, so the catastrophic multi-GB allocation can't happen.New status shape
useAudioWaveformnow returns a discriminated status:"idle" | "loading" | "ready" | "disabled" | "error"(pluswaveformand a retainedisLoadingflag for backward compatibility).TrimControlrenders based on status: the (previously unused)WaveformCanvasis wired in for normal files, and a static placeholder with helper text is shown whenstatus === "disabled".Cancellation / lifecycle
AudioContextor callingsetState, preventing updates on unmounted components and stale waveforms after a new file is selected.User experience
Testing
Commands run locally:
npx vitest run— 130 passed (15 files), including 9 new tests.npx next lint— no warnings or errors.npx next build— static export succeeds.New tests:
src/hooks/__tests__/useAudioWaveform.test.tsxstatus: "disabled") for very large files with an assertion thatslice/arrayBufferare never called — no full read,status: "error",ready.src/components/__tests__/TrimControl.test.tsxNotes
Scope is intentionally limited to waveform extraction — no changes to FFmpeg export flows or other behaviour. Types follow the existing patterns in the hook and components.
🤖 Generated with Claude Code