test: log source copy fast path blockers
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isSourceCopyFastPathEligible, type VideoExporterConfig } from "./videoExporter";
|
||||
import {
|
||||
getSourceCopyFastPathBlockers,
|
||||
isSourceCopyFastPathEligible,
|
||||
type VideoExporterConfig,
|
||||
} from "./videoExporter";
|
||||
|
||||
function createConfig(overrides: Partial<VideoExporterConfig> = {}): VideoExporterConfig {
|
||||
return {
|
||||
@@ -123,3 +127,14 @@ describe("isSourceCopyFastPathEligible", () => {
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSourceCopyFastPathBlockers", () => {
|
||||
it("reports the source-size mismatch that blocks copy-only export", () => {
|
||||
expect(
|
||||
getSourceCopyFastPathBlockers(createConfig({ height: 1080 }), {
|
||||
width: 1920,
|
||||
height: 1032,
|
||||
}),
|
||||
).toContain("output-size 1920x1080 differs from source 1920x1032");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -92,25 +92,39 @@ export function isSourceCopyFastPathEligible(
|
||||
config: VideoExporterConfig,
|
||||
videoInfo: { width: number; height: number },
|
||||
) {
|
||||
return (
|
||||
config.width === videoInfo.width &&
|
||||
config.height === videoInfo.height &&
|
||||
!config.webcamVideoUrl &&
|
||||
!hasActiveTimeRegions(config.trimRegions) &&
|
||||
!hasActiveSpeedRegions(config.speedRegions) &&
|
||||
!hasActiveTimeRegions(config.zoomRegions) &&
|
||||
!hasActiveTimeRegions(config.annotationRegions) &&
|
||||
!hasNativeCursorOverlay(config) &&
|
||||
!hasCursorHighlightOverlay(config) &&
|
||||
isDefaultCrop(config.cropRegion) &&
|
||||
(config.padding ?? 0) <= SOURCE_COPY_EPSILON &&
|
||||
(config.videoPadding ?? 0) <= SOURCE_COPY_EPSILON &&
|
||||
(config.borderRadius ?? 0) <= SOURCE_COPY_EPSILON &&
|
||||
!config.showShadow &&
|
||||
config.shadowIntensity <= SOURCE_COPY_EPSILON &&
|
||||
!config.showBlur &&
|
||||
(config.motionBlurAmount ?? 0) <= SOURCE_COPY_EPSILON
|
||||
);
|
||||
return getSourceCopyFastPathBlockers(config, videoInfo).length === 0;
|
||||
}
|
||||
|
||||
export function getSourceCopyFastPathBlockers(
|
||||
config: VideoExporterConfig,
|
||||
videoInfo: { width: number; height: number },
|
||||
) {
|
||||
const blockers: string[] = [];
|
||||
|
||||
if (config.width !== videoInfo.width || config.height !== videoInfo.height) {
|
||||
blockers.push(
|
||||
`output-size ${config.width}x${config.height} differs from source ${videoInfo.width}x${videoInfo.height}`,
|
||||
);
|
||||
}
|
||||
if (config.webcamVideoUrl) blockers.push("webcam overlay is enabled");
|
||||
if (hasActiveTimeRegions(config.trimRegions)) blockers.push("trim regions are present");
|
||||
if (hasActiveSpeedRegions(config.speedRegions)) blockers.push("speed regions are present");
|
||||
if (hasActiveTimeRegions(config.zoomRegions)) blockers.push("zoom regions are present");
|
||||
if (hasActiveTimeRegions(config.annotationRegions))
|
||||
blockers.push("annotation regions are present");
|
||||
if (hasNativeCursorOverlay(config)) blockers.push("editable cursor overlay is enabled");
|
||||
if (hasCursorHighlightOverlay(config)) blockers.push("cursor highlight overlay is enabled");
|
||||
if (!isDefaultCrop(config.cropRegion)) blockers.push("crop is not default");
|
||||
if ((config.padding ?? 0) > SOURCE_COPY_EPSILON) blockers.push("padding is not zero");
|
||||
if ((config.videoPadding ?? 0) > SOURCE_COPY_EPSILON) blockers.push("video padding is not zero");
|
||||
if ((config.borderRadius ?? 0) > SOURCE_COPY_EPSILON) blockers.push("roundness is not zero");
|
||||
if (config.showShadow || config.shadowIntensity > SOURCE_COPY_EPSILON) {
|
||||
blockers.push("shadow is enabled");
|
||||
}
|
||||
if (config.showBlur) blockers.push("background blur is enabled");
|
||||
if ((config.motionBlurAmount ?? 0) > SOURCE_COPY_EPSILON) blockers.push("motion blur is enabled");
|
||||
|
||||
return blockers;
|
||||
}
|
||||
|
||||
function isMp4Source(videoUrl: string, blob: Blob) {
|
||||
@@ -645,12 +659,22 @@ export class VideoExporter {
|
||||
}
|
||||
|
||||
private async trySourceCopyFastPath(videoInfo: { width: number; height: number }) {
|
||||
if (!isSourceCopyFastPathEligible(this.config, videoInfo)) {
|
||||
const blockers = getSourceCopyFastPathBlockers(this.config, videoInfo);
|
||||
if (blockers.length > 0) {
|
||||
console.info("[VideoExporter] source-copy fast path disabled", {
|
||||
blockers,
|
||||
output: { width: this.config.width, height: this.config.height },
|
||||
source: videoInfo,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const sourceBlob = await this.loadSourceBlob();
|
||||
if (!sourceBlob || !isMp4Source(this.config.videoUrl, sourceBlob)) {
|
||||
console.info("[VideoExporter] source-copy fast path disabled", {
|
||||
blockers: ["source is not a readable MP4"],
|
||||
source: videoInfo,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -665,6 +689,10 @@ export class VideoExporter {
|
||||
estimatedTimeRemaining: 0,
|
||||
phase: "finalizing",
|
||||
});
|
||||
console.info("[VideoExporter] using source-copy fast path", {
|
||||
source: videoInfo,
|
||||
bytes: sourceBlob.size,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user