Commit Graph
88 Commits
Author SHA1 Message Date
webadderall 0315155e4f perf: optimize application startup 2026-09-05 16:15:37 +10:00
webadderall 0af7b381c6 Prevent closed console streams from crashing Recordly 2026-09-05 05:15:40 +10:00
webadderall 3ca4a7540c Use native update prompts off macOS 2026-09-03 12:09:31 +10:00
young ae36ac8a88 Fix HUD capture protection across recording backends 2026-09-03 11:38:03 +10:00
webadderall 31831c72ba Address CodeRabbit lifecycle feedback 2026-09-02 20:27:25 +10:00
webadderall 2dc3d72510 Fix Windows app and webcam lifecycle 2026-09-02 20:27:24 +10:00
webadderall ffbc0adde9 Fix experimental update channel and toast 2026-08-31 18:50:39 +10:00
young d27aac7719 Add live announcements and experimental updates 2026-08-30 21:23:11 +10:00
young 69312518c2 Disable the extension system 2026-08-28 09:54:42 +10:00
webadderall f874297ad3 Show Recordly in the Windows taskbar 2026-08-25 19:23:15 +10:00
young 72688f4fcb Show Recordly in the macOS Dock 2026-08-25 19:04:38 +10:00
wiiiii123 57cae3cff0 Merge branch 'main' into fix/electron-permission-policy 2026-07-11 10:32:47 +07:00
wiiiii123 146dc6a180 fix(electron): scope capture permissions to the HUD 2026-07-10 12:43:12 +07:00
wiiiii123 eab81522e0 fix(electron): constrain renderer navigation 2026-07-10 05:46:22 +07:00
webadderall 79f1356652 Revert "fix(linux): route X11 capture through real sources"
This reverts commit 067070d405.
2026-06-05 10:31:28 +10:00
wiiiii123 0a5519382b fix(hud): restore clickability after webcam preview 2026-05-29 02:53:33 +07:00
wiiiii123 067070d405 fix(linux): route X11 capture through real sources 2026-05-29 00:48:59 +07:00
wiiiii123 fe828433ad fix(recording): stabilize capture quality and CUDA export canvas 2026-05-27 18:12:21 +07:00
webadderall 95dc2a4d4c Update Recordly app branding assets 2026-05-11 19:20:21 +10:00
Alan Trebugeais ccbeb5fa1d fix: webcam recording, now it works, alongside the microphone etc 2026-05-10 23:37:07 +02:00
wiiiii123 1efc9f1706 fix(electron): avoid cjs dirname binding collision 2026-05-08 20:07:36 +07:00
wiiiii123 211d6165f9 merge main into beta/pr410-native-gpu-export-test
# Conflicts:
#	electron/ipc/project/manager.ts
#	electron/ipc/register/export.ts
#	src/lib/exporter/modernVideoExporter.ts
2026-05-08 10:44:13 +07:00
webadderall 25cd1f2f75 Speed up Lightning export and relax local media reads 2026-05-08 11:32:04 +10:00
wiiiii123 3455475f38 fix(export): harden native beta pipeline 2026-05-07 22:37:27 +07:00
wiiiii123 9c81006e5c Add native GPU static layout export path 2026-05-03 22:43:23 +07:00
webadderall 624c3047be Improve HUD and update prompt UI 2026-04-25 21:34:55 +10:00
大彪 f8122bde18 chore(smoke-export): let the smoke harness open .recordly project files
Previously the smoke-export harness only accepted a raw MP4 input path.
Validating the export pipeline on a real editor project (with its own
zoom regions, wallpaper, annotations, and webcam state) required
opening the editor by hand and clicking through the GUI.

This adds three new environment variables that are picked up by the
existing smoke-export query string plumbing:

- RECORDLY_SMOKE_EXPORT_PROJECT  — path to a .recordly project file;
  when set, the editor opens it via openProjectFileAtPath and applies
  the saved state before the auto-export fires.
- RECORDLY_SMOKE_EXPORT_QUALITY  — overrides the hard-coded "good"
  quality used by the auto-export trigger; accepts medium / good /
  high / source.
- RECORDLY_SMOKE_EXPORT_FPS      — overrides the frame rate; accepts
  24 / 30 / 60.

No behavior change for existing RECORDLY_SMOKE_EXPORT_INPUT runs;
the new inputs are strictly additive and optional. The startup log
line prefers the project path over the raw-input path when both are
populated.
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 e70eabcfd3 Merge pull request #302 from meiiie/fix/linux-wayland-gpu-switches
fix(linux): avoid forcing EGL on Wayland
2026-04-23 12:37:18 +10:00
wiiiii123 92ee514f5e fix(recording): recover from fullscreen countdown failures 2026-04-21 20:46:37 +07:00
wiiiii123 be8c5ef821 fix(linux): avoid forcing EGL on Wayland 2026-04-21 02:49:08 +07:00
Uri b200deddca fix(linux/wayland): address PR review feedback
- electron/main.ts: treat missing sourceId on linux as portal sentinel
  so the request handler never calls getSources() (which itself opens
  an extra portal dialog) on fresh sessions.
- useScreenRecorder.ts: persist the synthesized portal sentinel via
  selectSource() so main has the source set before getDisplayMedia.
  Extract acquireLinuxPortalStream() helper to dedupe the three
  duplicated getDisplayMedia constraint blocks.
- LaunchWindow.tsx: hide the screen-source selector button (and its
  separator) on Linux so users cannot trigger an extra portal dialog
  via the dropdown.
2026-04-18 16:38:52 +03:00
Uri 571bbb9434 fix(linux/wayland): collapse 3-step capture flow into a single portal dialog
Previously on Linux/Wayland, starting a fullscreen recording required three
separate picker interactions: an in-app source dropdown plus two xdg-desktop-portal
dialogs. The duplicate portal dialogs were caused by:

1. resolveBrowserCaptureSource() calling desktopCapturer.getSources() in the
   renderer, which itself triggers the portal on Wayland.
2. setDisplayMediaRequestHandler() in main also calling getSources(), which
   triggers another portal.
3. Returning a pre-enumerated source id to Chromium, which on Wayland is stale
   and forces Chromium to re-prompt via the portal during MediaStream creation.

Additionally, the editor window failed to appear after recording on some
Wayland sessions because 'ready-to-show' did not fire reliably.

Changes:
- LaunchWindow: skip the in-app source dropdown on Linux and start recording
  directly; the OS portal becomes the source picker.
- useScreenRecorder: introduce a 'screen:linux-portal' sentinel source. When
  set, route capture through navigator.mediaDevices.getDisplayMedia() so the
  portal handles selection in a single dialog. Skip resolveBrowserCaptureSource
  for the sentinel to avoid an extra getSources() call.
- electron/main: in setDisplayMediaRequestHandler, when the sentinel is set,
  skip desktopCapturer.getSources() entirely and return a synthetic source so
  Chromium opens the portal exactly once for the actual capture.
- electron/windows: in createEditorWindow, also call win.show() from
  did-finish-load as a fallback for Linux/Wayland where ready-to-show may
  not fire.
2026-04-18 16:17:08 +03:00
webadderall 41249a9a19 refactor: remove redundant Linux platform guard in GPU config 2026-04-18 22:05:05 +10:00
webadderall d4a7c863e8 fix: Linux GPU fallback and HUD window show safety net
- Add Linux GPU config: use EGL (better Wayland compat), disable VAAPI
  video decoder/encoder (many distros ship broken drivers causing
  'vaInitialize failed' and preventing renderer from loading)
- Add ready-to-show fallback for HUD window: if did-finish-load never
  fires (GPU failure), show the window after 500ms via ready-to-show

Ref #261
2026-04-18 21:32:18 +10:00
webadderall 45b6879d86 fix: serve video files via local HTTP server to fix loading on Windows
On Windows, the packaged app serves the renderer from http://127.0.0.1:PORT,
which causes Chromium to block file:// URLs in <video> elements — even with
webSecurity disabled. This affects all users running the packaged build.

Add a local media HTTP server (random port) that streams approved video files
with range request support for seeking. The renderer now resolves video paths
through this server instead of using file:// URLs directly.

- electron/mediaServer.ts: HTTP server with path validation against
  approvedLocalReadPaths and Content-Range support
- IPC handler 'get-local-media-url' converts file paths to HTTP URLs
- resolveVideoUrl() in renderer falls back to file:// if server unavailable
- Improved <video> onError to log actual MediaError details

Fixes #244
2026-04-18 15:55:43 +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 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 2a155faaf6 Hotfix 1.1.17 2026-04-06 18:10:29 +10:00
webadderall 96d2ca9e5c Improve tray and packaged editor restore paths 2026-04-06 15:22:58 +10:00
webadderall 18812bda10 Fix Windows tray restore during recording 2026-04-05 23:23:16 +10:00
webadderall 498b5ef426 Load packaged renderer over localhost 2026-04-05 18:51:51 +10:00
webadderall 965d4efac7 fix(windows): align Win10 HUD restore with interactive fallback 2026-04-04 17:22:37 +11:00
webadderall 238281dcec configure smoke export window boot flow 2026-04-04 13:07:49 +11:00
webadderall c9f99ee498 fix(electron): Windows HUD visibility - moveTop after show, reassert mouse state on recording start 2026-04-02 21:09:32 +11:00
webadderall b08f4efb37 fix(electron): Win10 HUD click-through recovery 2026-04-02 16:29:51 +11:00
webadderall e8aa5ac5ad fix: add setDevicePermissionHandler for Windows 11 webcam access
Chromium (Electron 17+) requires setDevicePermissionHandler in addition
to setPermissionCheckHandler/setPermissionRequestHandler. Without it,
device-level access is silently denied on Windows 11 even though the
permission check passes, causing getUserMedia to throw NotAllowedError.
2026-03-30 15:41:01 +11:00
webadderall 9b5e612b96 fix: add Windows camera/microphone permission status logging
- Check systemPreferences.getMediaAccessStatus on Windows startup
- Log warnings when camera/mic access is denied so users know to check
  Windows Settings > Privacy > Camera/Microphone
2026-03-30 15:27:47 +11:00
webadderall 53c7aa7e77 feat(updater): Windows native notifications and toast window fixes
- Use native OS Notification on Windows instead of transparent overlay
  toast window (transparent BrowserWindows are unreliable on Windows)
- Set app user model ID on Windows for proper notification grouping
- Make toast window opaque with solid background on Windows
- Only set transparent body background on macOS for update-toast window
- Refactor UpdateToastWindow to inline styles for Windows compatibility
- Add primaryAction-based button rendering in toast UI
- Add polling fallback for toast payload in UpdateToastWindow
- Add global CSS variables for brand accent color
2026-03-29 19:30:02 +11:00
webadderall ac14768a62 fix: TCC permission handling for native helpers on macOS 26
- Add CGPreflightScreenCaptureAccess pre-check in Swift helper
- Add microphone TCC pre-flight when mic capture is requested
- Warm up TCC via desktopCapturer.getSources before spawning helper
- Request mic access from Electron before helper spawn
- Remove unreliable systemPreferences.getMediaAccessStatus pre-checks
- Add camera entitlements to plist files for webcam support
- Guard getScreen() calls behind app.isReady()
- Make tray icons lazy to avoid early screen access
- Suppress duplicate permission error alerts in renderer
2026-03-29 19:15:18 +11:00