From e7108ba87cef3aa45d06bd3cfa33ae2196d963bb Mon Sep 17 00:00:00 2001 From: AdityaNarayanPadhi Date: Tue, 2 Jun 2026 23:37:27 +0530 Subject: [PATCH 1/2] fix(preview): prevent memory leak and CPU overhead in thumbnail generator by aborting video stream and adding timeout fallback (#1500) --- src/components/ThumbnailStrip.tsx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/components/ThumbnailStrip.tsx b/src/components/ThumbnailStrip.tsx index f5094722..e5d6810e 100644 --- a/src/components/ThumbnailStrip.tsx +++ b/src/components/ThumbnailStrip.tsx @@ -45,6 +45,10 @@ export default function ThumbnailStrip({ const cancelThumbnailRun = useCallback(() => { lastRunIdRef.current += 1; + if (offscreenVideoRef.current) { + offscreenVideoRef.current.src = ""; + offscreenVideoRef.current.load(); + } }, []); const generateThumbnails = useCallback(async () => { @@ -97,8 +101,15 @@ export default function ThumbnailStrip({ const time = times[i] ?? 0; await new Promise((resolve) => { - const onSeeked = async () => { + let timeoutId: number | undefined; + + const cleanup = () => { video.removeEventListener("seeked", onSeeked); + if (timeoutId) window.clearTimeout(timeoutId); + }; + + const onSeeked = async () => { + cleanup(); if (lastRunIdRef.current !== runId) { resolve(); @@ -127,6 +138,13 @@ export default function ThumbnailStrip({ setProgress(Math.round(((i + 1) / times.length) * 100)); resolve(); }; + + // Setup timeout fallback (2 seconds max per seek to prevent hang) + timeoutId = window.setTimeout(() => { + cleanup(); + resolve(); + }, 2000); + video.addEventListener("seeked", onSeeked); video.currentTime = time; }); From aa212a5603873299b2945703144921eb7fab6809 Mon Sep 17 00:00:00 2001 From: AdityaNarayanPadhi Date: Wed, 3 Jun 2026 00:08:53 +0530 Subject: [PATCH 2/2] fix(audio): prevent browser OOM crash during waveform generation by skipping decoding on files larger than 100MB (#1501) --- src/hooks/useAudioWaveform.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hooks/useAudioWaveform.ts b/src/hooks/useAudioWaveform.ts index 25ed57d5..a46520d2 100644 --- a/src/hooks/useAudioWaveform.ts +++ b/src/hooks/useAudioWaveform.ts @@ -45,6 +45,13 @@ export function useAudioWaveform( return; } + // Skip decoding for files larger than 100MB to prevent browser OOM crash + if (file.size > 100 * 1024 * 1024) { + setWaveform([]); + setIsLoading(false); + return; + } + const AudioContextCtor = window.AudioContext || (window as BrowserWindow).webkitAudioContext;