Commit Graph
158 Commits
Author SHA1 Message Date
webadderall ae060e83fe Wait for wallpaper frames during export 2026-04-27 17:09:42 +10:00
webadderall 15cd2f15a3 Loop wallpaper videos during export 2026-04-27 16:50:30 +10:00
webadderall f1449073e6 Fix black video wallpaper exports 2026-04-27 16:22:57 +10:00
webadderall bbd46b44ac Fix video wallpaper sync and streamline updater UI 2026-04-27 15:48:38 +10:00
webadderall ca05a3fcc0 fix(webcam): correct sync offset direction 2026-04-26 20:10:38 +10:00
大彪 f05dc1f495 fix(export): address remaining PR #295 review threads
- Include `resolvedWebcamVideoUrl` in the dependency arrays for
  `captureProjectThumbnail` and `handleExport` so thumbnail capture and
  export settings stay in sync when the webcam URL refreshes.
- Clear `VideoMuxer.streamSink` before awaiting `closeIpcExportStream`
  in `finalize()` to close the race where a concurrent `destroy()` →
  `abortStream()` could try to close the same stream ID a second time.
2026-04-24 16:02:37 +08:00
大彪 9ac4dbd2e8 fix(export): stream MP4 output to disk to unblock >2 GiB exports
Long recordings (35-minute screencaps were the motivating case) fail at
the 99% "Finalizing" step with a RangeError once the muxed MP4 would
exceed V8's ~2 GiB per-ArrayBuffer limit. Both export paths accumulate
the whole file in renderer memory and round-trip it through IPC, so no
output size past that point can complete:

- Legacy: src/lib/exporter/muxer.ts uses mediabunny's BufferTarget,
  which holds the entire MP4 in a single ArrayBuffer. finalize() → Blob
  → blob.arrayBuffer() → ipcRenderer.invoke('write-exported-video-to-
  path', arrayBuffer, path) — every step wants a ≥2 GiB contiguous
  allocation.
- Lightning: native-video-export-finish did fs.readFile(finalizedPath)
  and shipped the bytes back to the renderer, which re-serialized them
  again. Same ceiling.

This change moves the finished MP4 across the renderer↔main boundary
via a temp file instead of an ArrayBuffer:

- New electron/ipc/export/exportStream.ts manages streaming temp files
  via fh.write(buf, 0, len, position) so out-of-order writes (moov box
  rewrites, etc.) stay safe. Each session lives in a 0700 mkdtemp()
  directory opened with O_CREAT | O_EXCL so a hostile local user on a
  shared tempdir cannot pre-plant a symlink at the predicted path.
- New renderer-facing IPCs: export-stream-open/write/close,
  finalize-exported-video (renames temp to final path, copy+unlink
  fallback on EXDEV/EPERM/ENOTEMPTY with console.warn on leaked bytes),
  mux-exported-video-audio-from-path (FFmpeg audio fallback that takes
  a path instead of an ArrayBuffer), and discard-exported-temp. Every
  handler validates the caller-supplied path against an owned-export-
  paths registry before touching disk, so a compromised renderer cannot
  route arbitrary filesystem paths into main-process deletes/moves.
- The muxer now picks mediabunny's StreamTarget automatically when the
  Electron bridge is available (BufferTarget stays for tests and any
  non-Electron callers). finalize() returns { mode, tempFilePath,
  bytesWritten } or { mode, blob } so the exporter can branch.
- Exporters forward tempFilePath through ExportResult. Lightning's
  finish returns the ffmpeg temp path directly; the FFmpeg audio
  fallback forks on the muxer result type. modernVideoExporter's
  Lightning success branch now accepts tempFilePath (previously it
  checked blob only, which regressed every native export).
- VideoEditor.tsx dispatches on tempFilePath: finalize via the new IPC,
  keep the temp in place when the save dialog is canceled so "Save
  Again" still works without re-rendering, keep the pending-save entry
  alive on non-canceled save failures, and discard the temp on unmount
  or explicit clear. GIF and smoke-test code paths still use the
  legacy Blob path unchanged.
- app.on('before-quit') also reaps any open streaming sessions via
  cleanupAllExportStreams().

Chunk size is 16 MiB — well under Electron/Mojo IPC message limits
while keeping total writes low (~160 for a 2.5 GB export).

Tested locally: exported a 35:13 source (~2.7 GiB H.264 input) at
Original 1920×1080 + Balanced. Previously failed on finalize with a
RangeError; with this patch the Legacy pipeline produced a valid 3.7
GiB MP4 whose ffmpeg -i duration/streams match the source.

Addresses #194.
2026-04-24 16:02:37 +08:00
webadderall 62f2a52860 Fix companion audio sync for trimmed and long exports 2026-04-24 12:04:21 +10:00
webadderall 05a6d3f1b6 Fix embedded audio fallback handling and audio diagnostics (#309)
* Fix embedded audio fallback handling and audio diagnostics

* Add recording fallback diagnostics toasts

* Fix Windows audio fallback cleanup and path matching

* Format rebased recording fallback changes

* Fix embedded audio preview and export fallback handling
2026-04-24 11:30:10 +10:00
webadderallandSehajveerSingh2005 282ccefedc Add independent padding controls
Co-authored-by: SehajveerSingh2005 <sehajveersingh2005@gmail.com>
2026-04-23 23:58:38 +10:00
wiiiii123 2b19493bb7 fix(export): validate edited-track fast-path inputs 2026-04-21 18:09:23 +07:00
wiiiii123 fcdc842371 fix(export): fast-path simple edited audio tracks 2026-04-21 18:09:23 +07:00
webadderall 4005687de4 fix(export): handle loopback media URLs during export 2026-04-21 19:22:05 +10:00
wiiiii123 ccc0e63d1b fix(export): clean telemetry profiling rebase 2026-04-20 20:11:58 +07:00
wiiiii123 b7e5a4ab79 chore(export): add ffmpeg mux timing breakdown 2026-04-20 20:09:54 +07:00
wiiiii123 8bc79ea1cd chore(export): add finalization stage profiling 2026-04-20 20:09:21 +07:00
wiiiii123 19486c7a44 fix(export): cancel timed out finalization work 2026-04-20 11:21:52 +07:00
wiiiii123 04e013cbbf fix(export): only refresh watchdog on progress 2026-04-20 10:39:10 +07:00
wiiiii123 6783eeb55c test(export): share finalization watchdog logic 2026-04-20 10:19:25 +07:00
wiiiii123 271dddcc32 fix(export): make audio timeouts progress-aware 2026-04-20 10:01:42 +07:00
wiiiii123 dc60a8e6e5 fix(export): scale audio finalization timeouts 2026-04-20 02:37:21 +07:00
webadderall 681bc70c13 fix: clear video src on timeout path in getMediaDurationSec 2026-04-18 22:04:40 +10:00
webadderall a0668696bc fix: address CodeRabbit review — fallback, i18n, return type cleanup
- Change ?? 99 fallback to ?? 100 in finalizing progress label
- Add editor.export.processingAudioEdits i18n key to all 5 locales
- Tighten sourceTimeToOutputTime return type to number (was number|null)
- Remove now-unused totalOutputDurationMs param from scheduleRegionForChunk
- Remove ?? fallbacks at call sites (function always returns a number)
2026-04-18 21:38:05 +10:00
webadderall ebe2bc5c16 fix: audio regions on silent video, interleaved >2ch stride, coderabbit config
- Fall back to video container duration when mainBuffer is null but
  audioRegions are present (prevents empty output)
- Use data.numberOfChannels as deinterleave stride instead of capped
  dataChannels (fixes garbled audio for 5.1+ sources)
- Fix .coderabbit.yaml: '*' is not valid regex, use '.*'
2026-04-18 20:45:46 +10:00
webadderall 028fd91ffd fix: address CodeRabbit review — muxing error guard, dead code removal, i18n
- Add encoderError check after awaiting pendingMuxing to prevent
  finalization of corrupt exports (both exporters)
- Remove unreachable synchronous fast-path in getMediaDurationSec
- Set preload='metadata' before src for correct browser behavior
- Localize audio processing status text with t()
2026-04-18 20:43:48 +10:00
webadderall cbe0b9feac fix: replace real-time audio export with streaming decode + chunked offline rendering
Major rewrite of the audio export pipeline for stability and memory efficiency:

## Streaming Decode
- Primary decode path uses WebDemuxer + AudioDecoder (WebCodecs streaming)
- Falls back to bulk decodeAudioData if streaming fails
- Avoids holding full compressed file + decoded PCM simultaneously

## Chunked Offline Rendering
- Processes timeline in 30-second OfflineAudioContext chunks
- Memory bounded to ~30s of PCM per chunk regardless of recording length

## Chunked WAV Writing
- Writes PCM in ~256KB chunks instead of single massive ArrayBuffer
- Eliminates OOM for long recordings on the native/FFmpeg export path

## Chunked Encoding
- Single AudioEncoder kept alive across all chunks (clean AAC stream)
- Proper backpressure and error propagation per chunk

## scheduleBufferThroughTimeline chunk windowing
- Clips source nodes to chunk boundaries for correct cross-chunk audio
- Backwards compatible defaults when no chunk params provided

## Other export fixes
- Progress cap: 99% -> 100% in both exporters and UI
- Muxing errors: propagated instead of silently swallowed
- Mac recording: enhanced warning when no audio files for muxing
- Export timeout: eliminated by removing real-time rendering
2026-04-18 20:29:14 +10:00
webadderall 8f3a62d811 fix: check both realpath and resolve forms in media URL handler, extract sync constants
- IPC get-local-media-url now checks both fs.realpath and path.resolve forms
  against approvedLocalReadPaths, so symlinks approved via approveUserPath work
- Extract duplicated sync correction parameters into shared constants in
  audioEncoder.ts (SYNC_SEEK_THRESHOLD_SEC, SYNC_PLAYBACK_RATE_OPTIONS)
2026-04-18 19:11:01 +10:00
webadderall ffc5959994 fix: address CodeRabbit review feedback
- Fix telemetry drift reset: use nextExpectedMs - now for delay instead
  of stale drift value after baseline reset (avoids 1ms rapid sample)
- Use RECORDER_TIMESLICE_MS for mic fallback recorder (was hardcoded 1000)
- Return requested timeMs in extensionHost getCursorAt boundary clamps
- Remove premature null of webcam URL to prevent flicker on path change
- Use fs.realpath in IPC get-local-media-url to match media server check
2026-04-18 19:03:36 +10:00
webadderall 9100899adb fix: improve cursor telemetry accuracy under CPU load
- Replace setInterval with drift-compensating recursive setTimeout for
  cursor sampling. Under CPU load setInterval bunches or skips callbacks,
  creating irregular gaps in telemetry data.
- Add binary search + linear interpolation to export cursor lookup
  (modernFrameRenderer) matching the playback path. Was using O(n)
  nearest-neighbor which caused visible cursor jumping in exports.
- Apply same interpolation fix to extension API getCursorAt().
2026-04-18 19:03:36 +10:00
webadderall f024c89890 fix: always apply aresample sync filter and tighten audio sync tolerances
- Always route audio through aresample=async=1:first_pts=0 filter during
  muxing on both macOS and Windows, even when duration delta is small.
  Previously skipped when delta ≤50ms, which left progressive clock drift
  (from CPU load) completely uncorrected.
- Lower sync detection threshold from 50ms to 20ms so tempo correction
  kicks in earlier.
- Use explicit 48kHz AudioContext sample rate in both browser recording
  and export rendering to prevent sample rate mismatch drift.
- Reduce MediaRecorder timeslice from 1000ms to 250ms to reduce chunk
  loss under CPU pressure.
- Tighten export audio sync: seek threshold 300ms→150ms, tolerance
  15ms→8ms, correction window 2s→0.5s, max adjustment ±8%→±12%.
- Lower companion audio start delay threshold from 50ms to 25ms.
2026-04-18 19:03:36 +10:00
webadderall d9b06bcfd9 Merge remote-tracking branch 'origin/main' into feat/settings-extensions
# Conflicts:
#	src/components/video-editor/ExtensionManager.tsx
#	src/components/video-editor/SettingsPanel.tsx
#	src/components/video-editor/TutorialHelp.tsx
#	src/components/video-editor/VideoEditor.tsx
#	src/components/video-editor/index.ts
#	src/components/video-editor/projectPersistence.ts
#	src/components/video-editor/timeline/TimelineEditor.tsx
#	src/components/video-editor/types.ts
#	src/i18n/locales/nl/launch.json
2026-04-17 13:58:36 +10:00
webadderall 8d925281fc Merge remote-tracking branch 'origin/main' into feat/export-pipeline
# Conflicts:
#	electron/electron-env.d.ts
#	electron/ipc/handlers.ts
2026-04-17 13:47:15 +10:00
webadderall e6ce742f58 fix: address final export pipeline review follow-ups 2026-04-17 00:41:32 +10:00
webadderall aa27e7cbd1 fix: address remaining export pipeline review feedback 2026-04-17 00:17:54 +10:00
webadderall a83a58c671 fix: address ui overhaul review feedback 2026-04-16 22:36:23 +10:00
webadderall 993c7aff9c fix: address settings and extensions review feedback 2026-04-16 19:16:20 +10:00
webadderall f81a740614 fix: address export pipeline review feedback 2026-04-16 18:49:01 +10:00
webadderall 9a5ff5c0a2 feat: ui overhaul — Phosphor icons, redesigned launcher, editor layout, and component refresh
- Replace all lucide-react imports with @phosphor-icons/react across every
  component (LaunchWindow, AnnotationSettingsPanel, ExtensionManager,
  ExtensionIcon, VideoPlayback, AnnotationOverlay, CropControl, TutorialHelp,
  PlaybackControls, all shadcn ui/ primitives, etc.)
- ExtensionIcon: new Phosphor-based resolver with Lucide name alias map for
  backwards-compatible extension manifests
- LaunchWindow / SourceSelector: full redesign — new icon rail layout,
  updated backgrounds, improved source selection UX, audio/video controls,
  countdown overlay
- VideoPlayback: overhaul playback controls and preview panel layout
- Timeline items: border-radius 16px→8px, cyan→blue unification, pill height
  85% for breathing room, resize handle vertical centering
- shadcn ui/: refresh accordion, dialog, dropdown, select, slider, switch,
  tabs, toggle, popover, button, card, input, label, sonner, content-clamp,
  audio-level-meter
- App.tsx / index.css / App.css / tailwind.config: global style updates
- types.ts, captionLayout.ts, captionStyle.ts, webcamOverlay.ts: data model
  updates to support new timeline and export features
- package.json: add @phosphor-icons/react, bump dependencies
- scripts/, .eslintrc, biome, tsconfig, vite.config: tooling alignment
- extension-sources: update built-in extension bundles
2026-04-16 18:01:04 +10:00
webadderall 48cdb5c203 feat: settings tab with language picker, extension fixes, and i18n expansion
- SettingsPanel: new 'settings' section — in-app language picker (all 5
  locales), auto-apply fresh recording zooms toggle, connect-neighboring-
  zooms toggle, keybinds shortcut into KeyboardShortcutsDialog
- VideoEditor: wire autoApplyFreshRecordingAutoZooms preference through to
  SettingsPanel; connect zoom settings into new section
- editorPreferences: add autoApplyFreshRecordingAutoZooms field; update tests
- extensionMarketplace: filter __MACOSX sidecar dirs when unzipping extensions
  uploaded from macOS Finder (fixes manifest-not-found on Finder zips)
- useExtensions: guard window.electronAPI for SSR safety; reformat to tabs
- I18nContext: expose setLocale; persist locale preference
- ShortcutsContext: shortcut registration improvements
- lib/extensions: renderHooks, extensionHost, fileUrls, cursorCoordinates
  updated for new extension capability surface
- i18n: expand extension locale strings across all 5 supported languages
2026-04-16 17:52:53 +10:00
webadderall 8abceaa914 feat: add H.264 stream-copy export, overhaul exporter pipeline, rename native binaries
- IPC: new inputMode 'h264-stream' — browser VideoEncoder output stream-copied
  into MP4 via ffmpeg rather than piping raw RGBA frames, cuts memory usage
- Security: replace flat approvedLocalReadPaths with userApprovedPaths fed from
  dialog pickers and project load; isAllowedLocalReadPath uses it alongside
  dir prefix / existsSync checks
- nativeVideoExport: add buildNativeH264StreamExportArgs for stream-copy path
- frameRenderer / modernFrameRenderer: cursor-follow camera integration,
  annotation blur post-processing, shadow profile, squircle geometry
- audioEncoder / streamingDecoder / gifExporter / muxer: full pipeline
  hardening — drift correction, backpressure, proper teardown
- Rename native helpers openscreen-* → recordly-* on darwin-arm64 and
  darwin-x64; update helpers-manifest.json for win32-x64
- electron/main, windows, updater, rendererServer: startup and window
  lifecycle improvements
- preload: expose inputMode and new IPC surface to renderer
2026-04-16 17:51:41 +10:00
webadderall 60d364a4ed fix: hotfix export regressions 2026-04-15 17:19:49 +10:00
Wing900 654ed79ba8 Fix silent MP4 exports with FFmpeg audio fallback 2026-04-12 20:55:34 +08:00
webadderall b2342090b2 feat(editor): full-width timeline, extension i18n, lifecycle fixes
- Move timeline below preview+settings so it spans full editor width
- Remove react-resizable-panels vertical split
- Add scoped i18n for ExtensionManager (en/zh/ko/ja/es)
- Fix stale extension activation cleanup and deactivation on uninstall
- Cache-bust extension module URLs on reinstall
- Move bundled cursor packs to extension-sources/ for marketplace upload
- Track marketplace download counts (fire-and-forget POST)
2026-04-12 16:59:07 +10:00
webadderall d6f1225e45 feat(extensions): marketplace integration, wallpaper thumbnails, cursor packs, and bug fixes
- Extension marketplace UI with browsing, installing, screenshot gallery
- Wallpaper & cursor style registration API for extensions
- Wallpaper thumbnail system (nativeImage resize + disk cache, OOM-safe)
- Fix HUD crash: check configurable before redefining electronAPI
- Fix zip-slip false positive on macOS (fs.realpath for symlinks)
- Extension icon sizing and description truncation improvements
- Eager extension activation in SettingsPanel
2026-04-12 01:38:36 +10:00
webadderall 5fc78fd90b feat(export): add extension render hooks to export pipeline
- Integrate extension render hooks into frameRenderer and modernFrameRenderer
- Add modernFrameRenderer for compositing extensions during export
- Wire extension audio processing in audioEncoder
- Support extension hooks in gif and video export paths
2026-04-12 01:38:36 +10:00
webadderall 7073d7deb5 feat: extension system with marketplace, permissions, and security hardening
- Extension loader with manifest validation, ID sanitization, and path traversal protection
- Permission-gated runtime API (render, cursor, audio, timeline, ui, assets, export)
- Extension host with lifecycle management (activate/deactivate)
- Marketplace client for browsing, downloading, and installing extensions
- Extension Manager UI panel with enable/disable/uninstall
- IPC bridge for extension discovery, management, and marketplace operations
- Proxy guard on window.electronAPI to block extension access to privileged IPC
- Zip-slip protection via post-extraction directory traversal validation
- Safe PowerShell invocation for Windows zip extraction (no string interpolation)
- File URL resolution with path escape prevention
2026-04-12 01:37:28 +10:00
webadderall dce398ee02 fix(export): render blur annotations in modern pipeline 2026-04-11 21:40:37 +10:00
Mahdy Arief 1567eebe8a feat(editor): enhance blur annotations with custom intensity, censorship color, and rounded corners 2026-04-11 08:06:45 +07:00
Mahdy Arief a7e65905df feat(editor): standardize blur strength, localize help text, and optimize export performance 2026-04-11 07:39:35 +07:00
Mahdy Arief 45ee7105ef feat(blur): implement video blur annotation support 2026-04-11 07:39:35 +07:00