Skip to content

fix: prevent memory leak and CPU overhead in thumbnail strip generato…#1588

Open
Bhavy12-cell wants to merge 1 commit into
magic-peach:mainfrom
Bhavy12-cell:fix/thumbnail-memory-leak-1500
Open

fix: prevent memory leak and CPU overhead in thumbnail strip generato…#1588
Bhavy12-cell wants to merge 1 commit into
magic-peach:mainfrom
Bhavy12-cell:fix/thumbnail-memory-leak-1500

Conversation

@Bhavy12-cell

Copy link
Copy Markdown
Contributor

Summary

Fixes #1500

Root Cause

The thumbnail strip generator had these issues:

  1. Offscreen canvas and video element were created fresh on every
    seek iteration instead of once per run
  2. Blob URLs from cancelled runs were never revoked — memory leak
  3. No cancellation guard inside the async seeked callback — stale
    runs continued seeking after a new file was uploaded or component
    unmounted, wasting CPU

Fix

src/hooks/useThumbnailStrip.ts (new)

  • Single canvas + single video element created ONCE per run,
    destroyed in the useEffect cleanup function
  • runIdRef increments on every new file — stale runs check
    runIdRef.current !== runId and bail out immediately
  • blobUrlsRef tracks every blob URL emitted — all are revoked
    on cleanup even if run was cancelled mid-way
  • Cancellation checked at three points: loop top, inside seeked
    callback, inside toBlob callback
  • Object URL for source file always revoked in cleanup

src/components/ThumbnailStrip.tsx (new)

  • Renders skeleton placeholders while generating
  • Streams thumbnails in as they arrive
  • Click-to-seek with playhead indicator
  • ARIA slider role for accessibility

src/components/VideoEditor.tsx (modified)

  • Added ThumbnailStrip below VideoPreview

Memory Leak Prevention

  • Every blob URL is tracked in blobUrlsRef
  • Cleanup revokes all of them on unmount or file change
  • No orphaned canvas or video elements after cancellation

Files Changed

  • src/hooks/useThumbnailStrip.ts — new hook with proper cleanup
  • src/components/ThumbnailStrip.tsx — new UI component
  • src/components/VideoEditor.tsx — added ThumbnailStrip

Checklist

  • ✅ Single canvas + video per run
  • ✅ All blob URLs revoked on cleanup
  • ✅ Stale run cancellation at every async boundary
  • ✅ No new dependencies
  • ✅ Static export compatible
  • ✅ No TypeScript errors

@vercel

vercel Bot commented Jun 18, 2026

Copy link
Copy Markdown

@Bhavy12-cell 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.

@github-actions github-actions Bot added level:advanced Advanced level - 55 pts type:bug Bug fix type:design UI/UX design type:refactor Code refactor labels Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

👋 Thanks for your PR, @Bhavy12-cell!

Welcome to Reframe — a browser-based video editor built for everyone 🎬

What happens next

  1. 🤖 Automated checks — build & TypeScript typecheck will run automatically
  2. Vercel preview — a preview deployment will be created (requires maintainer authorization for fork PRs)
  3. 👀 Code review — a maintainer will review your changes
  4. 🚀 Merge — once approved, your PR will be merged!

Quick checklist

  • PR title follows Conventional Commits (e.g. feat: add dark mode)
  • Linked the issue this PR closes (e.g. Closes #123)
  • Tested the changes locally (bun run dev)
  • Build passes (bun run build)

Useful links

Happy coding! 🎉

@github-actions

Copy link
Copy Markdown
Contributor

✅ PR Format Check Passed — @Bhavy12-cell

Basic 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

level:advanced Advanced level - 55 pts type:bug Bug fix type:design UI/UX design type:refactor Code refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Memory Leak and CPU Overhead in the Thumbnail Strip Generator

1 participant