mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 14:50:02 +00:00
FFmpeg 6.0 (bundled by ffmpeg-static) has a regression where -shortest combined with -c:v copy over-truncates the video stream while leaving audio untouched. The flag is also redundant — the audio mixer already pads/caps all tracks to totalDuration via apad=whole_dur and -t. Closes #1648
This commit is contained in:
@@ -394,10 +394,10 @@ describe("muxVideoWithAudio audio codec handling", () => {
|
|||||||
"make_zero",
|
"make_zero",
|
||||||
"-r",
|
"-r",
|
||||||
"30",
|
"30",
|
||||||
"-shortest",
|
|
||||||
"-y",
|
"-y",
|
||||||
"/tmp/output.mp4",
|
"/tmp/output.mp4",
|
||||||
]);
|
]);
|
||||||
|
expect(calls[0]!.args).not.toContain("-shortest");
|
||||||
expect(calls[0]!.args).not.toContain("-use_editlist");
|
expect(calls[0]!.args).not.toContain("-use_editlist");
|
||||||
|
|
||||||
emitClose(calls[0]!.proc, 0);
|
emitClose(calls[0]!.proc, 0);
|
||||||
@@ -545,6 +545,30 @@ describe("muxVideoWithAudio audio codec handling", () => {
|
|||||||
await expect(muxPromise).resolves.toMatchObject({ success: true });
|
await expect(muxPromise).resolves.toMatchObject({ success: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not pass -shortest to ffmpeg (regression #1648)", async () => {
|
||||||
|
const { spawn, calls } = createSpawnSpy();
|
||||||
|
vi.resetModules();
|
||||||
|
vi.doMock("child_process", () => ({ spawn }));
|
||||||
|
|
||||||
|
const { muxVideoWithAudio } = await import("./chunkEncoder.js");
|
||||||
|
|
||||||
|
for (const ext of [".mp4", ".mov", ".webm"] as const) {
|
||||||
|
const muxPromise = muxVideoWithAudio(
|
||||||
|
`/tmp/video-only${ext}`,
|
||||||
|
"/tmp/audio.aac",
|
||||||
|
`/tmp/output${ext}`,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
{ num: 30, den: 1 },
|
||||||
|
);
|
||||||
|
if (ext !== ".webm") await flushMuxCodecResolution();
|
||||||
|
const call = calls[calls.length - 1]!;
|
||||||
|
expect(call.args).not.toContain("-shortest");
|
||||||
|
emitClose(call.proc, 0);
|
||||||
|
await muxPromise;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps WebM audio on the Opus transcode path", async () => {
|
it("keeps WebM audio on the Opus transcode path", async () => {
|
||||||
const { spawn, calls } = createSpawnSpy();
|
const { spawn, calls } = createSpawnSpy();
|
||||||
vi.resetModules();
|
vi.resetModules();
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ export async function muxVideoWithAudio(
|
|||||||
// output container metadata. `-c:v copy` is retained; no re-encode.
|
// output container metadata. `-c:v copy` is retained; no re-encode.
|
||||||
args.push("-r", fpsToFfmpegArg(fps));
|
args.push("-r", fpsToFfmpegArg(fps));
|
||||||
}
|
}
|
||||||
args.push("-shortest", "-y", outputPath);
|
args.push("-y", outputPath);
|
||||||
|
|
||||||
const processTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
const processTimeout = config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
||||||
const result = await runFfmpeg(args, { signal, timeout: processTimeout });
|
const result = await runFfmpeg(args, { signal, timeout: processTimeout });
|
||||||
|
|||||||
Reference in New Issue
Block a user