Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/producer/src/services/render/stages/encodeStage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ describe("gif encode args", () => {
});

describe("runEncodeStage config plumbing", () => {
it("gives high-quality encodes enough budget for slow Windows libx264", async () => {
const { runEncodeStage } = await import("./encodeStage.js");
const input = makeInput();

await runEncodeStage(
makeInput({
job: {
...input.job,
config: { ...input.job.config, quality: "high" },
duration: 172.56,
},
engineConfig: { ffmpegEncodeTimeout: 600_000 },
}),
);

expect(encodeFramesFromDirMock.mock.calls[0]?.[5]).toEqual({
ffmpegEncodeTimeout: 4_141_440,
});
});

it("scales the encode timeout for long compositions", async () => {
const { runEncodeStage } = await import("./encodeStage.js");

Expand Down
11 changes: 7 additions & 4 deletions packages/producer/src/services/render/stages/encodeStage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,13 @@ export async function runEncodeStage(input: EncodeStageInput): Promise<EncodeSta
updateJobStatus(job, "encoding", "Encoding video", 75, onProgress);

// 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);
// A fixed ten-minute cap reliably kills long disk-frame encodes that are
// still making progress. High-quality libx264 can be substantially slower
// than standard presets on CPU-only Windows hosts, so give that preset the
// same conservative budget operators previously had to set by hand while
// retaining the established 4x budget for draft/standard renders.
const encodeBudgetPerSourceSecond = job.config.quality === "high" ? 24_000 : 4_000;
const scaledEncodeTimeout = Math.ceil((job.duration ?? 0) * encodeBudgetPerSourceSecond);
const videoEngineCfg =
scaledEncodeTimeout > engineCfg.ffmpegEncodeTimeout
? { ...engineCfg, ffmpegEncodeTimeout: scaledEncodeTimeout }
Expand Down
Loading