fix: bound HDR and video extraction resources (#2955)

* fix: bound HDR and video extraction resources

* fix: trim negative video extraction preroll

* fix: skip invisible video extraction windows

* fix: preserve negative-start loop and held tails

* fix: cap finite video slots to source duration

* fix: bound held-tail frame extraction

* fix: plan from playable video duration

* fix: preserve open-ended held video tails

* fix: resolve held tails from decoded frames

* fix: normalize final-frame probe timestamps

* fix: handle unseekable final-frame sources

* fix: dedupe final-frame probes per render

* refactor: clarify output dynamic range contract
This commit is contained in:
James Russo
2026-08-02 20:21:54 -07:00
committed by GitHub
parent 67ffafb11c
commit 2339757377
22 changed files with 2541 additions and 156 deletions
+46
View File
@@ -84,6 +84,7 @@ interface RenderInput {
quality: "draft" | "standard" | "high";
format?: "mp4" | "webm" | "mov";
videoFrameFormat?: RenderConfig["videoFrameFormat"];
outputDynamicRange?: "auto" | "hdr" | "sdr";
workers?: number;
useGpu: boolean;
debug: boolean;
@@ -158,6 +159,28 @@ function parseServerFormat(value: unknown): RenderInput["format"] {
return value === "mp4" || value === "webm" || value === "mov" ? value : undefined;
}
function parseServerOutputDynamicRange(value: unknown): RenderInput["outputDynamicRange"] {
return value === "auto" || value === "hdr" || value === "sdr" ? value : undefined;
}
function parseLegacyServerHdrMode(value: unknown): RenderConfig["hdrMode"] {
return value === "auto" || value === "force-hdr" || value === "force-sdr" ? value : undefined;
}
function fromRenderHdrMode(hdrMode: RenderConfig["hdrMode"]): RenderInput["outputDynamicRange"] {
if (hdrMode === "force-hdr") return "hdr";
if (hdrMode === "force-sdr") return "sdr";
return hdrMode;
}
function toRenderHdrMode(
outputDynamicRange: RenderInput["outputDynamicRange"],
): RenderConfig["hdrMode"] {
if (outputDynamicRange === "hdr") return "force-hdr";
if (outputDynamicRange === "sdr") return "force-sdr";
return outputDynamicRange;
}
export function parseRenderOptions(body: Record<string, unknown>): Omit<RenderInput, "projectDir"> {
// Accept either a JSON `number` (integer fps) or a JSON `string` (rational
// like "30000/1001"). Falls back to 30 fps on parse failure to preserve the
@@ -176,6 +199,9 @@ export function parseRenderOptions(body: Record<string, unknown>): Omit<RenderIn
const outputPath = parseOutputCandidate(body);
const entryFile = nonEmptyString(body.entryFile);
const format = parseServerFormat(body.format);
const outputDynamicRange =
parseServerOutputDynamicRange(body.outputDynamicRange) ??
fromRenderHdrMode(parseLegacyServerHdrMode(body.hdrMode));
const videoFrameFormat = isVideoFrameFormat(body.videoFrameFormat)
? body.videoFrameFormat
: undefined;
@@ -193,6 +219,7 @@ export function parseRenderOptions(body: Record<string, unknown>): Omit<RenderIn
strictness,
entryFile,
format,
outputDynamicRange,
variables,
outputResolution,
outputResolutionAspectAgnostic,
@@ -254,6 +281,7 @@ function buildRenderJobConfig(input: RenderInput, outputPath: string, log: Produ
outputResolution: input.outputResolution,
outputResolutionAspectAgnostic: input.outputResolutionAspectAgnostic,
videoFrameFormat: input.videoFrameFormat,
hdrMode: toRenderHdrMode(input.outputDynamicRange),
},
});
return renderConfigFromRequest(request, { logger: log });
@@ -286,6 +314,24 @@ function validateRenderOverrides(body: Record<string, unknown>): string | undefi
if (body.variables !== undefined && !isPlainObject(body.variables)) {
return 'variables must be a JSON object keyed by variable id (e.g. {"title":"Hello"})';
}
if (
body.outputDynamicRange !== undefined &&
parseServerOutputDynamicRange(body.outputDynamicRange) === undefined
) {
return 'outputDynamicRange must be one of: "auto", "hdr", "sdr"';
}
const legacyHdrMode = parseLegacyServerHdrMode(body.hdrMode);
if (body.hdrMode !== undefined && legacyHdrMode === undefined) {
return 'legacy hdrMode must be one of: "auto", "force-hdr", "force-sdr"';
}
const outputDynamicRange = parseServerOutputDynamicRange(body.outputDynamicRange);
if (
outputDynamicRange !== undefined &&
legacyHdrMode !== undefined &&
outputDynamicRange !== fromRenderHdrMode(legacyHdrMode)
) {
return "outputDynamicRange and legacy hdrMode must describe the same output policy";
}
return validateOutputResolutionOverride(body);
}