Address taskbar and rendering review feedback

This commit is contained in:
webadderall committed 2026-08-25 20:59:28 +10:00
1 parent b5bedd73d9
commit 83e2e5fbcf
6 files changed
+63 -16

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
import { describe, expect, it } from "vitest";
import { getHudOverlayTaskbarOptions } from "./hudOverlayWindowOptions";
describe("getHudOverlayTaskbarOptions", () => {
it("keeps a focusable HUD in the Windows taskbar", () => {
expect(getHudOverlayTaskbarOptions("win32")).toEqual({
skipTaskbar: false,
focusable: true,
});
});
it.each([
"darwin",
"linux",
] as const)("keeps the HUD non-focusable and out of the taskbar on %s", (platform) => {
expect(getHudOverlayTaskbarOptions(platform)).toEqual({
skipTaskbar: true,
focusable: false,
});
});
});
+12
View File
@@ -0,0 +1,12 @@
export interface HudOverlayTaskbarOptions {
skipTaskbar: boolean;
focusable: boolean;
}
export function getHudOverlayTaskbarOptions(platform: NodeJS.Platform): HudOverlayTaskbarOptions {
const showInWindowsTaskbar = platform === "win32";
return {
skipTaskbar: !showInWindowsTaskbar,
focusable: showInWindowsTaskbar,
};
}
+10 -8
View File
@@ -11,6 +11,7 @@ import {
buildNativeVideoExportArgs,
buildTrimmedSourceAudioFilter,
createNativeSquircleMaskPgmBuffer,
FFMPEG_BT709_VIDEO_COLOR_ARGS,
isNativeCudaOutOfMemory,
} from "./nativeVideoExport";
@@ -151,17 +152,15 @@ describe("native static layout command builders", () => {
expect(args).toContain("-filter_complex");
expect(args).toContain(
"color=c=0x101010:s=1920x1080:r=60:d=60.000,format=nv12,hwupload_cuda[bg];" +
"[0:v]scale_cuda=w=1536:h=864:format=nv12,fps=60[fg];" +
"color=c=0x101010:s=1920x1080:r=60:d=60.000,format=nv12,setrange=limited,hwupload_cuda[bg];" +
"[0:v]scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,scale=in_range=auto:out_range=tv,fps=60,hwupload_cuda[fg];" +
"[bg][fg]overlay_cuda=192:108:shortest=0:repeatlast=1:eof_action=repeat,trim=duration=60.000,setpts=PTS-STARTPTS[out]",
);
expect(args).toContain("h264_nvenc");
expect(args).toContain("p1");
expect(args).not.toContain("yuv420p");
expect(args).toEqual(expect.arrayContaining(["-ss", "120.000", "-t", "60.000"]));
expect(args).toEqual(
expect.arrayContaining(["-colorspace", "bt709", "-color_range", "tv"]),
);
expect(args).toEqual(expect.arrayContaining([...FFMPEG_BT709_VIDEO_COLOR_ARGS]));
});
it("converts full-range canvas pixels and tags native H.264 as BT.709 video range", () => {
@@ -199,12 +198,13 @@ describe("native static layout command builders", () => {
expect(args).toEqual(
expect.arrayContaining([
"-vf",
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,fps=60,pad=w=1920:h=1080:x=192:y=108:color=0x101010",
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,scale=in_range=auto:out_range=tv,fps=60,pad=w=1920:h=1080:x=192:y=108:color=0x101010",
"-map",
"0:v:0",
"-an",
]),
);
expect(args).toEqual(expect.arrayContaining([...FFMPEG_BT709_VIDEO_COLOR_ARGS]));
});
it("sanitizes unsupported background colors to the safe dark fallback", () => {
@@ -214,7 +214,7 @@ describe("native static layout command builders", () => {
});
expect(args).toContain(
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,fps=60,pad=w=1920:h=1080:x=192:y=108:color=0x101010",
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,scale=in_range=auto:out_range=tv,fps=60,pad=w=1920:h=1080:x=192:y=108:color=0x101010",
);
});
@@ -262,12 +262,14 @@ describe("native static layout command builders", () => {
expect(args).toEqual(expect.arrayContaining(["-i", "background.png", "-i", "mask.pgm"]));
expect(filterComplex).toContain(
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,fps=60,format=rgba",
"scale_cuda=w=1536:h=864:format=nv12:passthrough=0,hwdownload,format=nv12,scale=in_range=auto:out_range=full,fps=60,format=rgba",
);
expect(filterComplex).toContain("[fgbase][mask]alphamerge[fg]");
expect(filterComplex).toContain("overlay=x=192:y=108:format=auto");
expect(filterComplex).toContain("scale=in_range=full:out_range=tv,format=yuv420p[out]");
expect(args).toContain("h264_nvenc");
expect(args).toEqual(expect.arrayContaining(["-pix_fmt", "yuv420p"]));
expect(args).toEqual(expect.arrayContaining([...FFMPEG_BT709_VIDEO_COLOR_ARGS]));
});
it("creates an opaque PGM mask for square video corners and a partial mask for radius", () => {
+8 -4
View File
@@ -20,6 +20,10 @@ export const FFMPEG_BT709_VIDEO_COLOR_ARGS = [
"tv",
] as const;
const FFMPEG_AUTO_TO_VIDEO_RANGE_FILTER = "scale=in_range=auto:out_range=tv";
const FFMPEG_AUTO_TO_FULL_RANGE_FILTER = "scale=in_range=auto:out_range=full";
const FFMPEG_FULL_TO_VIDEO_RANGE_FILTER = "scale=in_range=full:out_range=tv";
export type NativeExportEncodingMode = "fast" | "balanced" | "quality";
export type NativeVideoExportAudioMode = "none" | "copy-source" | "trim-source" | "edited-track";
@@ -346,7 +350,7 @@ export function buildNativeCudaOverlayStaticLayoutArgs(
"-i",
config.inputPath,
"-filter_complex",
`color=c=${backgroundColor}:s=${config.width}x${config.height}:r=${config.frameRate}:d=${durationSec},format=nv12,hwupload_cuda[bg];[0:v]scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12,fps=${config.frameRate}[fg];[bg][fg]overlay_cuda=${config.offsetX}:${config.offsetY}:shortest=0:repeatlast=1:eof_action=repeat,trim=duration=${durationSec},setpts=PTS-STARTPTS[out]`,
`color=c=${backgroundColor}:s=${config.width}x${config.height}:r=${config.frameRate}:d=${durationSec},format=nv12,setrange=limited,hwupload_cuda[bg];[0:v]scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12:passthrough=0,hwdownload,format=nv12,${FFMPEG_AUTO_TO_VIDEO_RANGE_FILTER},fps=${config.frameRate},hwupload_cuda[fg];[bg][fg]overlay_cuda=${config.offsetX}:${config.offsetY}:shortest=0:repeatlast=1:eof_action=repeat,trim=duration=${durationSec},setpts=PTS-STARTPTS[out]`,
"-map",
"[out]",
"-an",
@@ -378,7 +382,7 @@ export function buildNativeCudaScaleCpuPadStaticLayoutArgs(
"-i",
config.inputPath,
"-vf",
`scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12:passthrough=0,hwdownload,format=nv12,fps=${config.frameRate},pad=w=${config.width}:h=${config.height}:x=${config.offsetX}:y=${config.offsetY}:color=${backgroundColor}`,
`scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12:passthrough=0,hwdownload,format=nv12,${FFMPEG_AUTO_TO_VIDEO_RANGE_FILTER},fps=${config.frameRate},pad=w=${config.width}:h=${config.height}:x=${config.offsetX}:y=${config.offsetY}:color=${backgroundColor}`,
"-map",
"0:v:0",
"-an",
@@ -534,10 +538,10 @@ export function buildNativePrecompositedStaticLayoutArgs(
);
}
const foregroundFilter = `[0:v]scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12:passthrough=0,hwdownload,format=nv12,fps=${config.frameRate},format=rgba[fgbase]`;
const foregroundFilter = `[0:v]scale_cuda=w=${config.contentWidth}:h=${config.contentHeight}:format=nv12:passthrough=0,hwdownload,format=nv12,${FFMPEG_AUTO_TO_FULL_RANGE_FILTER},fps=${config.frameRate},format=rgba[fgbase]`;
const maskFilter = useMask ? ";[2:v]format=gray[mask];[fgbase][mask]alphamerge[fg]" : "";
const foregroundLabel = useMask ? "fg" : "fgbase";
const filterComplex = `${foregroundFilter}${maskFilter};[1:v]format=rgba[bg];[bg][${foregroundLabel}]overlay=x=${config.offsetX}:y=${config.offsetY}:format=auto,trim=duration=${durationSec},setpts=PTS-STARTPTS,format=yuv420p[out]`;
const filterComplex = `${foregroundFilter}${maskFilter};[1:v]format=rgba[bg];[bg][${foregroundLabel}]overlay=x=${config.offsetX}:y=${config.offsetY}:format=auto,trim=duration=${durationSec},setpts=PTS-STARTPTS,${FFMPEG_FULL_TO_VIDEO_RANGE_FILTER},format=yuv420p[out]`;
args.push(
"-filter_complex",
+9 -3
View File
@@ -10,6 +10,7 @@ import {
resizeHudOverlayFallbackBounds,
shouldExpandHudOverlayFallback,
} from "./hudOverlayBounds";
import { getHudOverlayTaskbarOptions } from "./hudOverlayWindowOptions";
import { getPackagedRendererBaseUrl } from "./rendererServer";
const electronWindowsDir = path.dirname(fileURLToPath(import.meta.url));
@@ -466,10 +467,9 @@ export function createHudOverlayWindow(): BrowserWindow {
alwaysOnTop: true,
// The HUD is Recordly's persistent top-level window, so it owns the
// Windows taskbar entry while auxiliary overlays stay hidden there.
skipTaskbar: process.platform !== "win32",
...getHudOverlayTaskbarOptions(process.platform),
hasShadow: false,
show: false,
focusable: false,
webPreferences: {
preload: path.join(electronWindowsDir, "preload.mjs"),
nodeIntegration: false,
@@ -484,7 +484,13 @@ export function createHudOverlayWindow(): BrowserWindow {
return;
}
hasShownHudWindow = true;
win.show();
if (process.platform === "win32") {
// A focusable window is required for a Windows taskbar entry, but the
// always-on-top HUD must not steal focus when Recordly starts.
win.showInactive();
} else {
win.show();
}
win.moveTop();
if (process.platform === "win32" && isHudOverlayMousePassthroughSupported()) {
win.setIgnoreMouseEvents(false);
@@ -2948,7 +2948,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
<video
key={resolvedWallpaper}
ref={bgVideoRef}
className="absolute inset-0 h-full w-full object-cover"
className="absolute object-cover"
src={resolvedWallpaper}
muted
loop
@@ -2956,6 +2956,8 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
style={{
filter: backgroundBlur > 0 ? `blur(${backgroundBlur}px)` : "none",
inset: -backgroundBlurOverscan,
width: `calc(100% + ${backgroundBlurOverscan * 2}px)`,
height: `calc(100% + ${backgroundBlurOverscan * 2}px)`,
}}
/>
) : (