mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 23:05:49 +00:00
fix(export): keep Windows auto off static layout first
This commit is contained in:
@@ -27,8 +27,8 @@ describe("backendPolicy", () => {
|
||||
expect(getDefaultLightningRenderBackend()).toBe("webgl");
|
||||
});
|
||||
|
||||
it("puts visually compatible Windows auto exports on native static layout before Breeze", () => {
|
||||
expect(shouldPreferNativeStaticLayoutBeforeBreeze("win32", "auto")).toBe(true);
|
||||
it("keeps Windows auto exports on the streaming route by default", () => {
|
||||
expect(shouldPreferNativeStaticLayoutBeforeBreeze("win32", "auto")).toBe(false);
|
||||
expect(shouldPreferNativeStaticLayoutBeforeBreeze("darwin", "auto")).toBe(false);
|
||||
|
||||
expect(
|
||||
@@ -38,16 +38,16 @@ describe("backendPolicy", () => {
|
||||
nativeStaticLayoutAvailable: true,
|
||||
}),
|
||||
).toMatchObject({
|
||||
selectedRoute: "native-static-layout",
|
||||
selectedRoute: "breeze-stream",
|
||||
decisions: [
|
||||
{ route: "native-static-layout", status: "selected" },
|
||||
{ route: "breeze-stream", status: "fallback" },
|
||||
{ route: "native-static-layout", status: "rejected" },
|
||||
{ route: "breeze-stream", status: "selected" },
|
||||
{ route: "webcodecs", status: "fallback" },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("documents the Breeze fallback when Windows static native is rejected", () => {
|
||||
it("ignores native static skip reasons for Windows auto routing", () => {
|
||||
expect(
|
||||
planLightningExportRoutes({
|
||||
backendPreference: "auto",
|
||||
@@ -61,12 +61,12 @@ describe("backendPolicy", () => {
|
||||
{
|
||||
route: "native-static-layout",
|
||||
status: "rejected",
|
||||
reasons: ["unsupported-frame-overlay"],
|
||||
reasons: ["platform-does-not-use-native-static-layout"],
|
||||
},
|
||||
{
|
||||
route: "breeze-stream",
|
||||
status: "selected",
|
||||
reasons: ["windows-native-static-fallback"],
|
||||
reasons: ["platform-prefers-native-streaming"],
|
||||
},
|
||||
{
|
||||
route: "webcodecs",
|
||||
|
||||
@@ -41,11 +41,19 @@ export interface LightningExportRoutePlan {
|
||||
decisions: LightningExportRouteDecision[];
|
||||
}
|
||||
|
||||
// Disabled while stabilizing v1.3.0: the Windows auto static-layout probe can
|
||||
// leave Lightning at "Preparing export..." before the stable streaming fallback.
|
||||
const WINDOWS_AUTO_STATIC_LAYOUT_FIRST_ENABLED = false;
|
||||
|
||||
export function shouldPreferNativeStaticLayoutBeforeBreeze(
|
||||
platform: LightningRuntimePlatform,
|
||||
backendPreference: ExportBackendPreference,
|
||||
): boolean {
|
||||
return backendPreference === "auto" && platform === "win32";
|
||||
return (
|
||||
WINDOWS_AUTO_STATIC_LAYOUT_FIRST_ENABLED &&
|
||||
backendPreference === "auto" &&
|
||||
platform === "win32"
|
||||
);
|
||||
}
|
||||
|
||||
export function planLightningExportRoutes(options: {
|
||||
@@ -92,7 +100,7 @@ export function planLightningExportRoutes(options: {
|
||||
reasons: [
|
||||
options.backendPreference === "breeze"
|
||||
? "user-selected-breeze"
|
||||
: "windows-native-static-fallback",
|
||||
: "native-static-layout-not-auto-default",
|
||||
],
|
||||
});
|
||||
decisions.push({
|
||||
|
||||
@@ -118,7 +118,64 @@ describe("ModernVideoExporter native fallback routing", () => {
|
||||
expect(mocks.muxerFinalize).toHaveBeenCalledTimes(1);
|
||||
}, 15_000);
|
||||
|
||||
it("tries Windows auto static-layout before starting the streaming native encoder", async () => {
|
||||
it("keeps Windows auto exports on the streaming native route before static layout", async () => {
|
||||
vi.stubGlobal("navigator", {
|
||||
platform: "Win32",
|
||||
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
|
||||
});
|
||||
|
||||
const { ModernVideoExporter } = await import("./modernVideoExporter");
|
||||
const nativeResult = {
|
||||
success: true,
|
||||
blob: new Blob([], { type: "video/mp4" }),
|
||||
};
|
||||
const exporter = new ModernVideoExporter({
|
||||
videoUrl: "file:///recording.mp4",
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
frameRate: 30,
|
||||
bitrate: 8_000_000,
|
||||
wallpaper: "#101010",
|
||||
padding: 0,
|
||||
borderRadius: 0,
|
||||
backgroundBlur: 0,
|
||||
shadowIntensity: 0,
|
||||
showShadow: false,
|
||||
cropRegion: { x: 0, y: 0, width: 1, height: 1 },
|
||||
experimentalNativeExport: true,
|
||||
backendPreference: "auto",
|
||||
} as never) as unknown as {
|
||||
export: () => Promise<{ success: boolean; blob?: Blob; error?: string }>;
|
||||
finishNativeVideoExport: () => Promise<unknown>;
|
||||
loadNativeStaticLayoutVideoInfo: () => Promise<unknown>;
|
||||
tryExportNativeStaticLayout: () => Promise<unknown>;
|
||||
tryStartNativeVideoExport: () => Promise<boolean>;
|
||||
};
|
||||
|
||||
const loadNativeStaticLayoutVideoInfo = vi.spyOn(
|
||||
exporter,
|
||||
"loadNativeStaticLayoutVideoInfo",
|
||||
);
|
||||
const tryExportNativeStaticLayout = vi.spyOn(exporter, "tryExportNativeStaticLayout");
|
||||
const tryStartNativeVideoExport = vi
|
||||
.spyOn(exporter, "tryStartNativeVideoExport")
|
||||
.mockResolvedValue(true);
|
||||
const finishNativeVideoExport = vi
|
||||
.spyOn(exporter, "finishNativeVideoExport")
|
||||
.mockResolvedValue(nativeResult);
|
||||
|
||||
const result = await exporter.export();
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.blob).toBe(nativeResult.blob);
|
||||
expect(tryStartNativeVideoExport).toHaveBeenCalledTimes(1);
|
||||
expect(loadNativeStaticLayoutVideoInfo).not.toHaveBeenCalled();
|
||||
expect(tryExportNativeStaticLayout).not.toHaveBeenCalled();
|
||||
expect(mocks.streamingDecoderLoadMetadata).toHaveBeenCalledTimes(1);
|
||||
expect(finishNativeVideoExport).toHaveBeenCalledTimes(1);
|
||||
}, 15_000);
|
||||
|
||||
it("tries Windows auto static-layout first when NVIDIA CUDA is opted in", async () => {
|
||||
vi.stubGlobal("navigator", {
|
||||
platform: "Win32",
|
||||
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
|
||||
@@ -143,6 +200,7 @@ describe("ModernVideoExporter native fallback routing", () => {
|
||||
showShadow: false,
|
||||
cropRegion: { x: 0, y: 0, width: 1, height: 1 },
|
||||
experimentalNativeExport: true,
|
||||
experimentalNvidiaCudaExport: true,
|
||||
backendPreference: "auto",
|
||||
} as never) as unknown as {
|
||||
export: () => Promise<{ success: boolean; blob?: Blob; error?: string }>;
|
||||
|
||||
@@ -382,8 +382,12 @@ export class ModernVideoExporter {
|
||||
const runtimePlatform = this.getRuntimePlatform();
|
||||
let useNativeEncoder = false;
|
||||
let triedNativeStaticLayoutWithProbe = false;
|
||||
const shouldTryNativeStaticLayout =
|
||||
backendPreference === "breeze" ||
|
||||
this.config.experimentalNvidiaCudaExport === true;
|
||||
let shouldDeferNativeEncoderStart =
|
||||
backendPreference === "breeze" ||
|
||||
this.config.experimentalNvidiaCudaExport === true ||
|
||||
shouldPreferNativeStaticLayoutBeforeBreeze(runtimePlatform, backendPreference);
|
||||
this.lastNativeExportError = null;
|
||||
|
||||
@@ -478,10 +482,7 @@ export class ModernVideoExporter {
|
||||
maxInFlightNativeWrites: this.maxNativeWriteInFlight,
|
||||
});
|
||||
|
||||
if (
|
||||
(backendPreference === "auto" || backendPreference === "breeze") &&
|
||||
!useNativeEncoder
|
||||
) {
|
||||
if (shouldTryNativeStaticLayout && !useNativeEncoder) {
|
||||
const nativeVideoInfo = await this.loadNativeStaticLayoutVideoInfo();
|
||||
if (nativeVideoInfo) {
|
||||
triedNativeStaticLayoutWithProbe = true;
|
||||
@@ -530,7 +531,7 @@ export class ModernVideoExporter {
|
||||
const totalFrames = Math.ceil(effectiveDuration * this.config.frameRate);
|
||||
|
||||
if (
|
||||
(backendPreference === "auto" || backendPreference === "breeze") &&
|
||||
shouldTryNativeStaticLayout &&
|
||||
!useNativeEncoder &&
|
||||
!triedNativeStaticLayoutWithProbe
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user