From 90d04c734ee467206ea95861042f11c86c734c9c Mon Sep 17 00:00:00 2001 From: Raj Tiwari Date: Sat, 11 Apr 2026 13:07:07 +0530 Subject: [PATCH 1/4] fix(video): prioritize h264 codec and fix pixi render blur --- src/components/video-editor/VideoPlayback.tsx | 9 ++++++++- src/hooks/useScreenRecorder.ts | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index acc3f2e..f52c766 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -809,7 +809,6 @@ const VideoPlayback = forwardRef( blurFilter.resolution = app.renderer.resolution; blurFilter.blur = 0; const motionBlurFilter = new MotionBlurFilter([0, 0], 5, 0); - videoContainer.filters = [blurFilter, motionBlurFilter]; blurFilterRef.current = blurFilter; motionBlurFilterRef.current = motionBlurFilter; @@ -1081,6 +1080,14 @@ const VideoPlayback = forwardRef( motionIntensity, motionVector, ); + + const isMotionBlurActive = (motionBlurAmountRef.current || 0) > 0 && isPlayingRef.current; + + if (isMotionBlurActive && blurFilterRef.current && motionBlurFilterRef.current && videoContainerRef.current) { + videoContainerRef.current.filters = [blurFilterRef.current, motionBlurFilterRef.current]; + } else if (videoContainerRef.current) { + videoContainerRef.current.filters = null; + } }; app.ticker.add(ticker); diff --git a/src/hooks/useScreenRecorder.ts b/src/hooks/useScreenRecorder.ts index 2b07e24..2c21aac 100644 --- a/src/hooks/useScreenRecorder.ts +++ b/src/hooks/useScreenRecorder.ts @@ -118,11 +118,15 @@ export function useScreenRecorder(): UseScreenRecorderReturn { }, []); const selectMimeType = () => { + // H.264 first: hardware-accelerated on all modern devices, gives sharp + // real-time output. AV1/VP9 are great for distribution but too + // CPU-intensive for live 60 fps capture — they produce blurry frames + // when the software encoder can't keep up. const preferred = [ - "video/webm;codecs=av1", "video/webm;codecs=h264", - "video/webm;codecs=vp9", "video/webm;codecs=vp8", + "video/webm;codecs=vp9", + "video/webm;codecs=av1", "video/webm", ]; From f4e10b28cc23ede1d3529b568f24f7d2eae87da8 Mon Sep 17 00:00:00 2001 From: Raj Tiwari Date: Thu, 23 Apr 2026 22:50:21 +0530 Subject: [PATCH 2/4] style: fix linting errors for biome check --- src/components/ui/accordion.tsx | 2 +- src/components/ui/card.tsx | 2 +- src/components/ui/dialog.tsx | 12 ++++++------ src/components/ui/dropdown-menu.tsx | 14 +++++++------- src/components/ui/popover.tsx | 2 +- src/components/ui/select.tsx | 12 ++++++------ src/components/ui/tabs.tsx | 2 +- src/components/ui/tooltip.tsx | 2 +- src/components/video-editor/VideoPlayback.tsx | 7 ++++++- tsconfig.node.json | 7 ++++++- vite.config.ts | 12 +----------- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx index 85336fd..22456b2 100644 --- a/src/components/ui/accordion.tsx +++ b/src/components/ui/accordion.tsx @@ -52,4 +52,4 @@ const AccordionContent = React.forwardRef< )); AccordionContent.displayName = AccordionPrimitive.Content.displayName; -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; +export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }; diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index 2935ed4..0480764 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -52,4 +52,4 @@ const CardFooter = React.forwardRef( const isMotionBlurActive = (motionBlurAmountRef.current || 0) > 0 && isPlayingRef.current; - if (isMotionBlurActive && blurFilterRef.current && motionBlurFilterRef.current && videoContainerRef.current) { + if ( + isMotionBlurActive && + blurFilterRef.current && + motionBlurFilterRef.current && + videoContainerRef.current + ) { videoContainerRef.current.filters = [blurFilterRef.current, motionBlurFilterRef.current]; } else if (videoContainerRef.current) { videoContainerRef.current.filters = null; diff --git a/tsconfig.node.json b/tsconfig.node.json index 1caabef..3be14b6 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -7,5 +7,10 @@ "allowSyntheticDefaultImports": true, "strict": true }, - "include": ["vite.config.ts"] + "include": [ + "vite.config.ts", + "electron-builder.json5", + "playwright.config.ts", + "vitest.config.ts" + ] } diff --git a/vite.config.ts b/vite.config.ts index 9a44766..5d014d4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,25 +9,15 @@ export default defineConfig({ react(), electron({ main: { - // Shortcut of `build.lib.entry`. entry: "electron/main.ts", vite: { build: {}, }, }, preload: { - // Shortcut of `build.rollupOptions.input`. - // Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`. input: path.join(__dirname, "electron/preload.ts"), }, - // Ployfill the Electron and Node.js API for Renderer process. - // If you want use Node.js in Renderer process, the `nodeIntegration` needs to be enabled in the Main process. - // See https://github.com/electron-vite/vite-plugin-electron-renderer - renderer: - process.env.NODE_ENV === "test" - ? // https://github.com/electron-vite/vite-plugin-electron-renderer/issues/78#issuecomment-2053600808 - undefined - : {}, + renderer: process.env.NODE_ENV === "test" ? undefined : {}, }), ], resolve: { From a26eb3cbab31437a35e238996bfa43fa236ee7ae Mon Sep 17 00:00:00 2001 From: Raj Tiwari Date: Thu, 23 Apr 2026 22:55:40 +0530 Subject: [PATCH 3/4] perf: cache motion blur state in ticker --- src/components/video-editor/VideoPlayback.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index 48d3631..7b7ce55 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -856,7 +856,7 @@ const VideoPlayback = forwardRef( videoContainer.mask = null; maskGraphicsRef.current = null; if (blurFilterRef.current) { - videoContainer.filters = []; + videoContainer.filters = null; blurFilterRef.current.destroy(); blurFilterRef.current = null; } @@ -913,6 +913,7 @@ const VideoPlayback = forwardRef( state.appliedScale = appliedTransform.scale; }; + let lastMotionBlurActive: boolean | null = null; const ticker = () => { const bm = baseMaskRef.current; const ss = stageSizeRef.current; @@ -1083,15 +1084,16 @@ const VideoPlayback = forwardRef( const isMotionBlurActive = (motionBlurAmountRef.current || 0) > 0 && isPlayingRef.current; - if ( - isMotionBlurActive && - blurFilterRef.current && - motionBlurFilterRef.current && - videoContainerRef.current - ) { - videoContainerRef.current.filters = [blurFilterRef.current, motionBlurFilterRef.current]; - } else if (videoContainerRef.current) { - videoContainerRef.current.filters = null; + if (isMotionBlurActive !== lastMotionBlurActive && videoContainerRef.current) { + if (isMotionBlurActive && blurFilterRef.current && motionBlurFilterRef.current) { + videoContainerRef.current.filters = [ + blurFilterRef.current, + motionBlurFilterRef.current, + ]; + } else { + videoContainerRef.current.filters = null; + } + lastMotionBlurActive = isMotionBlurActive; } }; From 8e1c7e035af95fc0416b0c6335a38f3ef993325f Mon Sep 17 00:00:00 2001 From: Raj Tiwari Date: Thu, 23 Apr 2026 23:02:04 +0530 Subject: [PATCH 4/4] fix: correct motion blur state caching logic --- src/components/video-editor/VideoPlayback.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index 7b7ce55..f15a801 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -1085,15 +1085,18 @@ const VideoPlayback = forwardRef( const isMotionBlurActive = (motionBlurAmountRef.current || 0) > 0 && isPlayingRef.current; if (isMotionBlurActive !== lastMotionBlurActive && videoContainerRef.current) { - if (isMotionBlurActive && blurFilterRef.current && motionBlurFilterRef.current) { - videoContainerRef.current.filters = [ - blurFilterRef.current, - motionBlurFilterRef.current, - ]; + if (isMotionBlurActive) { + if (blurFilterRef.current && motionBlurFilterRef.current) { + videoContainerRef.current.filters = [ + blurFilterRef.current, + motionBlurFilterRef.current, + ]; + lastMotionBlurActive = true; + } } else { videoContainerRef.current.filters = null; + lastMotionBlurActive = false; } - lastMotionBlurActive = isMotionBlurActive; } };