mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
fix(producer): scale high-quality encode timeout (#3649)
This commit is contained in:
@@ -259,6 +259,65 @@ describe("runEncodeStage config plumbing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("gives the reported long high-quality encode a 24x source-duration budget", async () => {
|
||||
const { runEncodeStage } = await import("./encodeStage.js");
|
||||
const input = makeInput();
|
||||
|
||||
await runEncodeStage(
|
||||
makeInput({
|
||||
job: {
|
||||
...input.job,
|
||||
config: { ...input.job.config, quality: "high" },
|
||||
duration: 331.273,
|
||||
},
|
||||
engineConfig: { ffmpegEncodeTimeout: 600_000 },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(encodeFramesFromDirMock.mock.calls[0]?.[5]).toEqual({
|
||||
ffmpegEncodeTimeout: 7_950_552,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the 4x budget for a standard encode", async () => {
|
||||
const { runEncodeStage } = await import("./encodeStage.js");
|
||||
const input = makeInput();
|
||||
|
||||
await runEncodeStage(
|
||||
makeInput({
|
||||
job: {
|
||||
...input.job,
|
||||
config: { ...input.job.config, quality: "standard" },
|
||||
duration: 331.273,
|
||||
},
|
||||
engineConfig: { ffmpegEncodeTimeout: 600_000 },
|
||||
}),
|
||||
);
|
||||
|
||||
expect(encodeFramesFromDirMock.mock.calls[0]?.[5]).toEqual({
|
||||
ffmpegEncodeTimeout: 1_325_092,
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves a larger operator timeout for high-quality encoding", async () => {
|
||||
const { runEncodeStage } = await import("./encodeStage.js");
|
||||
const input = makeInput();
|
||||
const operatorConfig = { ffmpegEncodeTimeout: 9_000_000 };
|
||||
|
||||
await runEncodeStage(
|
||||
makeInput({
|
||||
job: {
|
||||
...input.job,
|
||||
config: { ...input.job.config, quality: "high" },
|
||||
duration: 331.273,
|
||||
},
|
||||
engineConfig: operatorConfig,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(encodeFramesFromDirMock.mock.calls[0]?.[5]).toBe(operatorConfig);
|
||||
});
|
||||
|
||||
it("prefers engine config supplied by the orchestrator", async () => {
|
||||
const { runEncodeStage } = await import("./encodeStage.js");
|
||||
const orchestratorEngineConfig = { ffmpegEncodeTimeout: 54_321 };
|
||||
|
||||
@@ -289,9 +289,11 @@ export async function runEncodeStage(input: EncodeStageInput): Promise<EncodeSta
|
||||
|
||||
// ffmpegEncodeTimeout is a total wall-clock cap, not an inactivity timeout.
|
||||
// A fixed ten-minute cap reliably kills long high-quality disk-frame encodes
|
||||
// that are still making progress. Preserve larger operator overrides while
|
||||
// guaranteeing four seconds of encode budget per second of source video.
|
||||
const scaledEncodeTimeout = Math.ceil((job.duration ?? 0) * 4_000);
|
||||
// that are still making progress. High-quality CPU presets are substantially
|
||||
// slower, so reserve 24x source duration there while retaining the established
|
||||
// 4x budget for draft/standard and preserving larger operator overrides.
|
||||
const baseScaledEncodeTimeout = Math.ceil((job.duration ?? 0) * 4_000);
|
||||
const scaledEncodeTimeout = baseScaledEncodeTimeout * (job.config.quality === "high" ? 6 : 1);
|
||||
const videoEngineCfg =
|
||||
scaledEncodeTimeout > engineCfg.ffmpegEncodeTimeout
|
||||
? { ...engineCfg, ffmpegEncodeTimeout: scaledEncodeTimeout }
|
||||
|
||||
Reference in New Issue
Block a user