feat: add NVENC hardware encoding support for FFmpeg
Add FFMPEG_PREFER_HARDWARE env var to enable hardware acceleration Use h264_nvenc and hevc_nvenc encoders when hardware preferred Fall back to software encoders (libx264/libx265) when disabled Add comprehensive tests for hardware/software encoding modes Update README with new environment variable documentation This enables GPU-accelerated video encoding for better performance on systems with NVIDIA GPUs.
This commit is contained in:
parent
911587ea68
commit
6cca431a76
3 changed files with 75 additions and 2 deletions
|
|
@ -95,6 +95,7 @@ All are optional, JWT_SECRET is recommended to be set.
|
|||
| WEBROOT | | The address to the root path setting this to "/convert" will serve the website on "example.com/convert/" |
|
||||
| FFMPEG_ARGS | | Arguments to pass to the input file of ffmpeg, e.g. `-hwaccel vaapi`. See https://github.com/C4illin/ConvertX/issues/190 for more info about hw-acceleration. |
|
||||
| FFMPEG_OUTPUT_ARGS | | Arguments to pass to the output of ffmpeg, e.g. `-preset veryfast` |
|
||||
| FFMPEG_PREFER_HARDWARE | false | Use hardware encoders (NVENC, VAAPI, etc.) when available instead of software encoders for h264/h265 formats |
|
||||
| HIDE_HISTORY | false | Hide the history page |
|
||||
| LANGUAGE | en | Language to format date strings in, specified as a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag) |
|
||||
| UNAUTHENTICATED_USER_SHARING | false | Shares conversion history between all unauthenticated users |
|
||||
|
|
|
|||
|
|
@ -712,15 +712,27 @@ export async function convert(
|
|||
const split = convertTo.split(".");
|
||||
const codec_short = split[0];
|
||||
|
||||
// Check if hardware encoding is preferred (NVENC, VAAPI, etc.)
|
||||
const preferHardware = process.env.FFMPEG_PREFER_HARDWARE === "true" ||
|
||||
process.env.FFMPEG_PREFER_HARDWARE === "1";
|
||||
|
||||
switch (codec_short) {
|
||||
case "av1":
|
||||
extraArgs.push("-c:v", "libaom-av1");
|
||||
break;
|
||||
case "h264":
|
||||
extraArgs.push("-c:v", "libx264");
|
||||
if (preferHardware) {
|
||||
extraArgs.push("-c:v", "h264_nvenc");
|
||||
} else {
|
||||
extraArgs.push("-c:v", "libx264");
|
||||
}
|
||||
break;
|
||||
case "h265":
|
||||
extraArgs.push("-c:v", "libx265");
|
||||
if (preferHardware) {
|
||||
extraArgs.push("-c:v", "hevc_nvenc");
|
||||
} else {
|
||||
extraArgs.push("-c:v", "libx265");
|
||||
}
|
||||
break;
|
||||
case "h266":
|
||||
extraArgs.push("-c:v", "libx266");
|
||||
|
|
|
|||
|
|
@ -121,6 +121,66 @@ 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;
|
||||
|
||||
expect(calls[0]).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;
|
||||
|
||||
expect(calls[0]).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("respects FFMPEG_ARGS", async () => {
|
||||
process.env.FFMPEG_ARGS = "-hide_banner -y";
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue