Repository navigation
feat: export profiles, safe-area guides, correct Fill preview - #1836
Merged
Merged
Conversation
…entation UI - One design system on the existing tokens (--bg/--surface/--border/--text/ --muted unchanged) plus surface-2, border-strong, accent-text, on-accent, focus, status, radius and motion tokens; film-red accent used sparingly - System font stack (no font requests); defines the font-heading/display and animate-fade-in utilities that were used everywhere but never existed - Editor layout: preview first with a toolbar below it, edit tools as accordions with value summaries, sticky Output panel with pinned Export - High-contrast theme is now reachable (toggle + prefers-contrast) - Clearer upload, export, error/retry and success states; honest format and size copy; shared .btn/.choice/.field component classes Performance - Remove the universal transition and `transition: all`; reduced-motion support - Stop re-rendering the editor on every timeupdate; debounce URL sync - Thumbnails: capped, abortable, seek timeouts, batched, URLs revoked - Lazy-load Datadog; drop looping Lottie animations; fix privacy-banner CLS - Worker: dedupe progress, always pass -t (#1289 only patched the unused copy), cap encoder threads under cross-origin isolation (core-mt deadlock) - Restart the worker after a failed export; settle loads on terminate Telemetry: privacy-safe export/ffmpeg/thumbnail events and duration vitals, action-name masking, query strings stripped. Tests: 61 new (175 total). Lighthouse mobile (local build): 86 -> 100, LCP 3.40s -> 1.12s, CLS 0.096 -> 0. See docs/PERFORMANCE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- vercel.json: drop the redundant legacy `routes` block. With it, Vercel compiled the header rule after `handle: filesystem`, so no header reached static pages (confirmed with an offline `vercel build`). Leave HSTS to Vercel's stronger default. - One FFmpeg command builder (src/lib/ffmpegArgs.ts) used by the worker. Sharpness and volume were silently ignored by the copy that actually ran. - Cap decoder/filter/encoder threads only when the multi-threaded core loaded; fall back to the single-threaded core if core-mt fails to load. - Stall watchdog with worker heartbeats: a wedged export fails with an actionable message and retries on the single-threaded core. - WebM: VP8 + Vorbis. libvpx-vp9 and libopus trap in @ffmpeg/core 0.12.10, so WebM exports never succeeded (also on main). - Fix a hung "Exporting" state on id-less worker errors, a leaked log listener, cancel during engine load, and string rejections from wasm traps. - RUM never starts on localhost/LAN/automated browsers unless a non-production env is set; beforeSend scrubs file names, captions, paths and query strings from auto-collected events. - Tests for the real worker command path, deploy config, telemetry env and sanitising; scripts/perf/matrix.js and check-headers.mjs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Palette tokens from the reference (near-black, slate, warm brown, charcoal, warm ivory); warm brown marks selection, film red is kept for Export/Download, playhead, trim range and progress. High contrast intact. - Self-hosted Cormorant Garamond (next/font, no runtime request) for headings, the wordmark and the export percentage; system sans for every control. - Source / Edit / Output sections with parenthetical markers, hairline separators instead of cards, pill buttons, hairline sliders and progress. - Dark "screen" drop zone, numbered two-stage export dialog with a large serif percentage, serif completion panel with a Keep editing action. - CSS-only motion: masked headline rise, staggered fades, frame settle, grid-row disclosures (closed content is visibility:hidden), hover zoom on thumbnails. Reduced motion disables all of it; nothing animates the LCP element or the <video>. - Export dialog no longer announces every percent to screen readers. - Tooling: bench.js detects collapsed panels with checkVisibility(); local server serves contact.html for /contact like Vercel. Stabilised a flaky render-count test baseline. Lighthouse (mobile, median of 5): perf 100, LCP 1.10s -> 1.40s, CLS 0, +78 KB fonts. See docs/PERFORMANCE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Replace the Google Fonts Cormorant Garamond files (variable 300-700, Latin-1) with subsets of the styles the UI uses: upright 400-500 variable (18 KB, preloaded) and italic 400 static (12 KB), ASCII plus typographic punctuation. Built reproducibly by scripts/fonts/build-cormorant.sh from a pinned google/fonts commit; OFL included. - Lighthouse mobile, median of 5 vs e887f10: LCP 1,404 -> 1,253 ms, transfer 281 -> 235 KB, CLS 0. - Remove role="status" from the download panel: completion was announced twice and the whole panel (file name field included) read out. - Align the mobile/tablet export bar with the page gutters. - docs/PERFORMANCE.md: font audit, corrected LCP element, browser checks, limitations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Production (Netlify) is cross-origin isolated, so every browser loads the multi-threaded core. With FFmpeg choosing its own thread count, core-mt's 32-worker pool deadlocks and every export sits at "Exporting 100%" forever. Reproduced locally with COOP/COEP for MP4, WebM, portrait and no-audio inputs; the single-threaded core was unaffected. Ports the export hardening from the earlier branch (33b2c5a, bf26cf1): - src/lib/ffmpegArgs.ts: one command builder used by the worker (the old copy in ffmpeg.ts was dead code); decoder, filter and encoder threads capped at 4 on the multi-threaded core only - stall watchdog with worker heartbeats: 60 s without activity fails the export with ExportStalledError, and later attempts use the single-threaded core - WebM uses VP8 + Vorbis: libvpx-vp9 and libopus trap in @ffmpeg/core 0.12.10 - SRI hashes for the multi-threaded core files; falls back to the single-threaded core if core-mt fails to load - id-less worker errors, cancel during engine load, and string rejections from wasm traps no longer leave the editor stuck Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ests - Live-recorded files (MediaRecorder screen recordings) report an Infinity duration; seek to the end to find the real one (src/lib/mediaDuration.ts), in the editor and the export. Trim works on them again. - ffmpegArgs: time values are repaired before use (withSafeTimes), -t only for a finite positive length, -shortest for looped music when the length is unknown, and a final check that no argument carries Infinity or NaN. An infinite speed no longer hangs the audio filter builder. - Watchdog: besides 60 s of silence, stop exports whose encoded time stops changing for 120 s while FFmpeg keeps logging (stuck at 100%), or that run far past the expected length. The worker reports encoded time and computes progress from it. The message says what happened and to press Retry. - Telemetry: unknown_duration failure category and stall_reason. - scripts/make-fixtures.sh (test/fixtures/, gitignored), a static server with COOP/COEP (scripts/serve-isolated.mjs), Playwright export tests on the multi- and single-threaded engines, and a Tests workflow running Vitest and Playwright in CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…read default 2 - Threads per stage are min(4, navigator.hardwareConcurrency || 2); the fallback for an unreported core count was 4. - When the multi-threaded engine stalls, exportVideo retries the same export (same file and edits) once on the single-threaded engine instead of failing. The overlay says so, and RUM gets engine_fallback with the stall reason; the attempt's single outcome then carries engine "single" and fell_back. - A single-threaded stall, or a stall after cancelling, is not retried; the error tells the user to press Retry. - The editor passes the duration it already read to the export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They are untracked local copies (names ending in " 2"), not project files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion-e2e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # docs/DATADOG.md # src/lib/ffmpeg.ts # src/lib/tests/exportTelemetry.test.ts
export_cancelled carries stuck: true when the progress percentage hadn't changed for 60 s, so monitors can count a user giving up on a hang as a failure instead of an ordinary cancellation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merges the editorial "screening room" UI (031c44f, on top of ec05d58) into the export-fix branch, keeping everything main gained since: - undo/redo controls (in the Edit section header), the project panel and the recovery notice from #1822, restyled to the new design - overlay settings stay in the undoable edit state; the separate overlay localStorage effects from the old UI are dropped - the engine-fallback notice from #1831 in the new export dialog - FFmpeg, worker and telemetry code stay at their current versions; the old copies in the merged commit are not used - the hook keeps ExportAttempt telemetry and saved projects, and takes the redesign's describeExportError, outputDimensions, debounced URL sync and getCurrentTime (no re-render per video frame) page.tsx takes the redesign's version on purpose: main's nests a second <main id="main-content"> inside layout.tsx's, and the GitHub link moves into the header. docs/PERFORMANCE.md and scripts/perf from the old branch are not brought over (superseded by docs/DATADOG.md and the Playwright tests). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The worker wraps the output in a Blob and posts it; building it on the
page copied the whole file synchronously (1.2 s for a 300 MB export).
- The worker reads the user's File itself; the page no longer holds a copy
of the input (a 300 MB read caused multi-second GC pauses).
- Export dialog: an estimate of the time left once there is enough signal.
- Preset buttons have accessible names again ("1 is to 1 output ratio,
Square"); the redesign left them unnamed.
- e2e: a sequence of edits (trim, 9:16, rotate, 2x, mute) checked in the
output, including a pixel check that the rotation was applied, and a
smoothness suite: long tasks during export, cancel at both stages with no
leaked object URLs, and trim/scrub responsiveness on the 300 MB clip.
- Before/after screenshots in docs/assets/ui-redesign/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ported from bf2ec0d onto the redesigned editor (cherry-picked; the original commit is unchanged): - Built-in profiles (Landscape 1080p/720p, Square 1080, Portrait 4:5 and 9:16) plus profiles you save, rename and delete; applying one is a single undo step that keeps trims and overlays. Stored in localStorage. - Safe-area guides (90% / 80%) in the preview; preview-only, never exported. - The Fill preview crops like the encoder (src/lib/framing.ts), and resolveOutputSize is shared by the worker and the UI. - Anonymous feature usage: feature_used for profile apply/save/rename/ delete (built-in slug or "custom", never a name) and safe-area show/hide. - Accessibility: framing buttons get explicit names (the two-line content left them unnamed). - Playwright: four profile × framing × format exports checked by size, replacing the old puppeteer script. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Contributor
👋 Thanks for your PR, @magic-peach!Welcome to Reframe — a browser-based video editor built for everyone 🎬 What happens next
Quick checklist
Useful links
Happy coding! 🎉 |
No content change: main's tree equals d0429cf, which this branch builds on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
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.
Stacked on #1835 (the redesign). Merge that first, then change this PR's base to
main.Option D: export profiles, ported from the earlier branch (
bf2ec0d) onto the redesigned editor. This is Phase 5 item 2, brought forward because you chose C and D together.What it adds
src/lib/framing.tscomputes the frame from the real source aspect ratio with the encoder's rule, andresolveOutputSizeis shared by the worker and the UI.docs/EXPORT_PROFILES.md.Changes from the original commit
Usage telemetry, newly added (one of your Phase 5 rules): a
feature_usedevent for profile apply, save, rename and delete, and for safe-area show and hide. It carries the built-in slug orcustom, never a profile's name, which is user text (src/lib/featureTelemetry.ts, with tests). Documented indocs/DATADOG.md.Accessibility: the redesign's Fit and Fill buttons had no accessible name, so they now have explicit labels. The profile buttons already had them: "Square 1080, 1080 × 1080, MP4, Fit".
scripts/perf/profiles.js(puppeteer) is replaced bytest/e2e/profiles.spec.ts(Playwright, both engines). It applies a profile in the real UI, sets framing and format, shows the safe area, exports and checks the size:The README line from the original commit is left out to avoid clashing with docs: rewrite README; deployment, usage and contributing guides; credits #1833's rewrite. Once both are merged, the feature belongs in the README feature list and
docs/USAGE.md.Checks run locally
main.