Merge f71d5558c7 into 393441faa1
This commit is contained in:
commit
adccfed81b
3 changed files with 420 additions and 17 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { beforeEach, expect, test } from "bun:test";
|
||||
import { convert } from "../../src/converters/ffmpeg";
|
||||
import { convert, resetNvidiaGpuCache } from "../../src/converters/ffmpeg";
|
||||
|
||||
let calls: string[][] = [];
|
||||
|
||||
|
|
@ -11,6 +11,58 @@ function mockExecFile(
|
|||
calls.push(args);
|
||||
if (args.includes("fail.mov")) {
|
||||
callback(new Error("mock failure"), "", "Fake stderr: fail");
|
||||
} else if (_cmd === "nvidia-smi") {
|
||||
// Mock nvidia-smi - assume GPU is available for tests
|
||||
callback(
|
||||
null,
|
||||
"GPU 0: NVIDIA GeForce RTX 3080 (UUID: GPU-12345678-1234-1234-1234-123456789012)\n",
|
||||
"",
|
||||
);
|
||||
} else if (_cmd === "ffprobe") {
|
||||
// Mock ffprobe responses for codec detection
|
||||
// Return H.264 codec for .mp4 files, no video stream for images
|
||||
if (args.includes("in.mp4") || args.includes("in.mkv") || args.includes("in.avi")) {
|
||||
callback(
|
||||
null,
|
||||
JSON.stringify({
|
||||
streams: [
|
||||
{
|
||||
codec_type: "video",
|
||||
codec_name: "h264",
|
||||
},
|
||||
],
|
||||
}),
|
||||
"",
|
||||
);
|
||||
} else if (args.includes("in.jpg") || args.includes("in.png")) {
|
||||
// Image files have no video stream
|
||||
callback(
|
||||
null,
|
||||
JSON.stringify({
|
||||
streams: [
|
||||
{
|
||||
codec_type: "audio",
|
||||
codec_name: "pcm",
|
||||
},
|
||||
],
|
||||
}),
|
||||
"",
|
||||
);
|
||||
} else {
|
||||
// Default: assume H.264 for video files
|
||||
callback(
|
||||
null,
|
||||
JSON.stringify({
|
||||
streams: [
|
||||
{
|
||||
codec_type: "video",
|
||||
codec_name: "h264",
|
||||
},
|
||||
],
|
||||
}),
|
||||
"",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
callback(null, "Fake stdout", "");
|
||||
}
|
||||
|
|
@ -19,6 +71,9 @@ function mockExecFile(
|
|||
beforeEach(() => {
|
||||
calls = [];
|
||||
delete process.env.FFMPEG_ARGS;
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
// Reset the GPU availability cache between tests
|
||||
resetNvidiaGpuCache();
|
||||
});
|
||||
|
||||
test("converts a normal file", async () => {
|
||||
|
|
@ -121,6 +176,138 @@ test("uses libx266 for h266.mp4", async () => {
|
|||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
});
|
||||
|
||||
test("uses h264_nvenc for h264.mp4 when hardware preferred", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "true";
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.mkv", "mkv", "h264.mp4", "out.mp4", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
// calls[0] is nvidia-smi, calls[1] is ffprobe, calls[2] is ffmpeg
|
||||
expect(calls[2]).toEqual(expect.arrayContaining(["-c:v", "h264_nvenc"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
});
|
||||
|
||||
test("uses hevc_nvenc for h265.mp4 when hardware preferred", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "true";
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.mkv", "mkv", "h265.mp4", "out.mp4", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
// calls[0] is nvidia-smi, calls[1] is ffprobe, calls[2] is ffmpeg
|
||||
expect(calls[2]).toEqual(expect.arrayContaining(["-c:v", "hevc_nvenc"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
});
|
||||
|
||||
test("uses libx264 for h264.mp4 when hardware not preferred", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "false";
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.mkv", "mkv", "h264.mp4", "out.mp4", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
expect(calls[0]).toEqual(expect.arrayContaining(["-c:v", "libx264"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
});
|
||||
|
||||
test("adds CUDA hwaccel for video input when hardware preferred", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "true";
|
||||
delete process.env.FFMPEG_ARGS;
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.mp4", "mp4", "avi", "out.avi", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
// calls[0] is nvidia-smi, calls[1] is ffprobe, calls[2] is ffmpeg
|
||||
expect(calls[2]).toEqual(expect.arrayContaining(["-hwaccel", "cuda"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
});
|
||||
|
||||
test("does not add CUDA hwaccel for image input when hardware preferred", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "true";
|
||||
delete process.env.FFMPEG_ARGS;
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.jpg", "jpg", "png", "out.png", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
// calls[0] is nvidia-smi, calls[1] is ffprobe, calls[2] is ffmpeg
|
||||
expect(calls[2]).not.toEqual(expect.arrayContaining(["-hwaccel", "cuda"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
});
|
||||
|
||||
test("does not add CUDA hwaccel if FFMPEG_ARGS already specifies hwaccel", async () => {
|
||||
process.env.FFMPEG_PREFER_HARDWARE = "true";
|
||||
process.env.FFMPEG_ARGS = "-hwaccel vaapi";
|
||||
|
||||
const originalConsoleLog = console.log;
|
||||
|
||||
let loggedMessage = "";
|
||||
console.log = (msg) => {
|
||||
loggedMessage = msg;
|
||||
};
|
||||
|
||||
await convert("in.mp4", "mp4", "avi", "out.avi", undefined, mockExecFile);
|
||||
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
// When FFMPEG_ARGS already has hwaccel, no ffprobe call is made
|
||||
// calls[0] is nvidia-smi, calls[1] is ffmpeg
|
||||
// Should use vaapi from FFMPEG_ARGS, not add cuda
|
||||
expect(calls[1]).toEqual(expect.arrayContaining(["-hwaccel", "vaapi"]));
|
||||
expect(calls[0]).not.toEqual(expect.arrayContaining(["-hwaccel", "cuda"]));
|
||||
expect(loggedMessage).toBe("stdout: Fake stdout");
|
||||
|
||||
delete process.env.FFMPEG_PREFER_HARDWARE;
|
||||
delete process.env.FFMPEG_ARGS;
|
||||
});
|
||||
|
||||
test("respects FFMPEG_ARGS", async () => {
|
||||
process.env.FFMPEG_ARGS = "-hide_banner -y";
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue