feat: add live output preview frame before export#1076
Conversation
|
@skypank-coder 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. |
✅ PR Format Check Passed — @skypank-coderBasic 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. |
👋 Thanks for your PR, @skypank-coder!Welcome to Reframe — a browser-based video editor built for everyone 🎬
What happens next
Quick checklist
Useful links
Happy coding! 🎉 |
|
Hey @magic-peach — just wanted to flag that issue #1052 was assigned to me via |
Description
Reframe had no way to preview edit settings before committing to a full export,
meaning users discovered wrong crop, rotation, or framing only after waiting
30–90 seconds for FFmpeg to process the entire file. This PR adds a "Preview
Frame" button that extracts a single JPEG frame at the midpoint of the trimmed
range using the identical filtergraph as the real export — guaranteeing true
WYSIWYG feedback in under 2 seconds. The feature is purely additive and the
existing export pipeline is completely untouched.
Related Issue
Closes #1052
Type of Contribution
Participant Info
What Changed
src/lib/ffmpeg.ts— refactored filter graph builder into standalone exportedbuildFilterGraph()function; addedgeneratePreviewFrame()that usesinput-side seeking (
-ssbefore-i) to extract a single JPEG frame at thetrimmed range midpoint with the full filter chain applied; virtual FS files
cleaned up in
finallyblock with unique session IDs to prevent collisionssrc/hooks/useVideoEditor.ts— addedpreviewUrl: string | nullandisPreviewing: booleanstate; addedgeneratePreviewaction with guardagainst concurrent export; blob URL revoked on new preview, on file change,
and on unmount to prevent memory leaks
src/components/PreviewPanel.tsx— new component with Preview button, loadingstate, and frame display using Next.js
<Image>withunoptimizedfor blobURL support; all interactive elements have
aria-labelsrc/components/VideoEditor.tsx— mounted<PreviewPanel>below existingcontrols, passing
previewUrl,isPreviewing,generatePreview,isDisabled,and
isExportingpropsTechnical Notes
The
-ssseek flag is placed before-i(input-side seek) so FFmpeg jumpsdirectly to the midpoint without decoding the entire file, keeping preview
latency under 2 seconds on typical hardware. The
generatePreviewFramefunctionreceives the already-loaded FFmpeg WASM instance as a parameter — no
re-initialization occurs. Blob URLs are revoked via
URL.revokeObjectURLbeforeeach new preview and on unmount to prevent memory accumulation. Preview is
disabled while an export is running.
Testing Done
bun run lintpasses — zero warnings, zero errorsbunx tsc --noEmitpasses — zero errorsScreen Recording
Recording / Loom link:
GSSOC.REFRAME.1.1.mp4
Checklist
bun run lintpasses (no ESLint errors)bunx tsc --noEmitpasses (no TypeScript errors)aria-label/ accessible namesconsole.logstatements left in