diff --git a/electron/native/ScreenCaptureKitRecorder.swift b/electron/native/ScreenCaptureKitRecorder.swift index c5cd8fabf..d8757f03b 100644 --- a/electron/native/ScreenCaptureKitRecorder.swift +++ b/electron/native/ScreenCaptureKitRecorder.swift @@ -107,12 +107,17 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput, SCStreamDelegate { throw NSError(domain: "RecordlyCapture", code: 3, userInfo: [NSLocalizedDescriptionKey: "Window not found"]) } - filter = SCContentFilter(desktopIndependentWindow: window) - let candidateDisplay = availableContent.displays.first(where: { $0.frame.intersects(window.frame) || $0.frame.contains(CGPoint(x: window.frame.midX, y: window.frame.midY)) }) - let scaleFactor = ScreenCaptureRecorder.scaleFactor(for: candidateDisplay?.displayID ?? CGMainDisplayID()) + + guard let display = candidateDisplay else { + throw NSError(domain: "RecordlyCapture", code: 4, userInfo: [NSLocalizedDescriptionKey: "No intersecting display found for window"]) + } + + filter = SCContentFilter(display: display, including: [window], exceptingApplications: [], exceptingWindows: []) + + let scaleFactor = ScreenCaptureRecorder.scaleFactor(for: display.displayID) outputWidth = max(2, Int(window.frame.width) * scaleFactor) outputHeight = max(2, Int(window.frame.height) * scaleFactor) if #available(macOS 14.0, *) { @@ -655,8 +660,8 @@ guard CommandLine.arguments.count >= 2 else { } // Force CoreGraphics Services initialization on the main thread. -// Without this, SCContentFilter(desktopIndependentWindow:) crashes with -// CGS_REQUIRE_INIT because CGS is never initialised in a CLI tool. +// Without this, CoreGraphics operations may fail with CGS_REQUIRE_INIT +// because CGS is never initialised in a CLI tool. let _ = CGMainDisplayID() // Pre-flight check: ensure screen recording permission is granted before diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index c64e6b425..f1048bc71 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -1097,20 +1097,24 @@ const VideoPlayback = forwardRef( if (!frameData) return false; if (frameData.draw) { - // Resolution-independent: draw at a reasonable size, Pixi handles the rest - const drawW = 1920; - const drawH = 1080; - const canvas = document.createElement("canvas"); - canvas.width = drawW; - canvas.height = drawH; - const ctx = canvas.getContext("2d"); - if (ctx) frameData.draw(ctx, drawW, drawH); - if (cancelled || frameIdRef.current !== frame) return true; - const texture = Texture.from(canvas); - const sprite = new Sprite(texture); - frameSpriteRef.current = sprite; - container.addChild(sprite); - layoutVideoContentRef.current?.(); + try { + // Resolution-independent: draw at a reasonable size, Pixi handles the rest + const drawW = 1920; + const drawH = 1080; + const canvas = document.createElement("canvas"); + canvas.width = drawW; + canvas.height = drawH; + const ctx = canvas.getContext("2d"); + if (ctx) frameData.draw(ctx, drawW, drawH); + if (cancelled || frameIdRef.current !== frame) return true; + const texture = Texture.from(canvas); + const sprite = new Sprite(texture); + frameSpriteRef.current = sprite; + container.addChild(sprite); + layoutVideoContentRef.current?.(); + } catch (err) { + console.error(`[VideoPlayback] Failed to draw frame '${frameData.id}':`, err); + } } else { const img = new Image(); img.onload = () => { @@ -1121,6 +1125,9 @@ const VideoPlayback = forwardRef( container.addChild(sprite); layoutVideoContentRef.current?.(); }; + img.onerror = (err) => { + console.error(`[VideoPlayback] Failed to load frame image from '${frameData.filePath}':`, err); + }; img.src = frameData.filePath; } return true;