155 lines
3.2 KiB
TypeScript
155 lines
3.2 KiB
TypeScript
|
type VideoEncodePreset = {
|
||
|
id: string;
|
||
|
codec: "av1";
|
||
|
preset: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||
|
mbitMax?: number;
|
||
|
crf: number;
|
||
|
maxHeight?: number;
|
||
|
audioKbit?: number;
|
||
|
depth?: 8 | 10;
|
||
|
} | {
|
||
|
id: string;
|
||
|
codec: "vp9";
|
||
|
crf: number;
|
||
|
mbitMax?: number;
|
||
|
maxHeight?: number;
|
||
|
audioKbit?: number;
|
||
|
};
|
||
|
|
||
|
export const videoFormats = [
|
||
|
{
|
||
|
id: "au", // AV1 Ultra-High
|
||
|
codec: "av1",
|
||
|
preset: 1,
|
||
|
crf: 28,
|
||
|
depth: 10,
|
||
|
},
|
||
|
{
|
||
|
id: "vu", // VP9 Ultra-High
|
||
|
codec: "vp9",
|
||
|
crf: 30,
|
||
|
},
|
||
|
{
|
||
|
id: "ah", // AV1 High
|
||
|
preset: 2,
|
||
|
codec: "av1",
|
||
|
mbitMax: 5,
|
||
|
crf: 35,
|
||
|
depth: 10,
|
||
|
},
|
||
|
{
|
||
|
id: "am", // AV1 Medium
|
||
|
preset: 2,
|
||
|
codec: "av1",
|
||
|
mbitMax: 2,
|
||
|
crf: 40,
|
||
|
maxHeight: 900,
|
||
|
},
|
||
|
{
|
||
|
id: "vm", // VP9 Medium
|
||
|
codec: "vp9",
|
||
|
crf: 35,
|
||
|
mbitMax: 4,
|
||
|
maxHeight: 1080,
|
||
|
},
|
||
|
{
|
||
|
id: "al", // AV1 Low
|
||
|
preset: 2,
|
||
|
codec: "av1",
|
||
|
mbitMax: 1.25,
|
||
|
crf: 40,
|
||
|
maxHeight: 600,
|
||
|
},
|
||
|
{
|
||
|
id: "vl", // VP9 Low
|
||
|
codec: "vp9",
|
||
|
crf: 45,
|
||
|
mbitMax: 2,
|
||
|
maxHeight: 600,
|
||
|
},
|
||
|
{
|
||
|
id: "ad", // AV1 Data-saving
|
||
|
codec: "av1",
|
||
|
preset: 1,
|
||
|
mbitMax: 0.5,
|
||
|
crf: 10,
|
||
|
maxHeight: 360,
|
||
|
},
|
||
|
{
|
||
|
id: "vl", // VP9 Low
|
||
|
codec: "vp9",
|
||
|
crf: 10,
|
||
|
mbitMax: 0.75,
|
||
|
maxHeight: 360,
|
||
|
},
|
||
|
] satisfies VideoEncodePreset[] as VideoEncodePreset[];
|
||
|
|
||
|
export const imageSizes = [64, 128, 256, 512, 1024, 2048];
|
||
|
export const imagePresets = [
|
||
|
{
|
||
|
ext: ".webp",
|
||
|
args: [
|
||
|
"-lossless",
|
||
|
"0",
|
||
|
"-compression_level",
|
||
|
"6",
|
||
|
"-quality",
|
||
|
"95",
|
||
|
"-method",
|
||
|
"6",
|
||
|
],
|
||
|
},
|
||
|
// TODO: avif
|
||
|
{
|
||
|
ext: ".jxl",
|
||
|
args: ["-c:v", "libjxl", "-distance", "0.8", "-effort", "9"],
|
||
|
},
|
||
|
];
|
||
|
|
||
|
export function getVideoArgs(preset: VideoEncodePreset, outbase: string, input: string[]) {
|
||
|
const cmd = [...input];
|
||
|
|
||
|
if (preset.codec === "av1") {
|
||
|
cmd.push("-c:v", "libsvtav1");
|
||
|
cmd.push(
|
||
|
"-svtav1-params",
|
||
|
[
|
||
|
`preset=${preset.preset}`,
|
||
|
"keyint=2s",
|
||
|
preset.depth && `input-depth=${preset.depth}`, // EncoderBitDepth
|
||
|
`crf=${preset.crf}`, // ConstantRateFactor
|
||
|
preset.mbitMax && `mbr=${preset.mbitMax}m`, // MaxBitRate
|
||
|
"tune=1", // Tune, PSNR
|
||
|
"enable-overlays=1", // EnableOverlays
|
||
|
"fast-decode=1", // FastDecode
|
||
|
"scm=2", // ScreenContentMode, adaptive
|
||
|
].filter(Boolean).join(":"),
|
||
|
);
|
||
|
} else if (preset.codec === "vp9") {
|
||
|
// Not much research has gone into this, since it is only going to be used on old Safari browsers.
|
||
|
cmd.push("-c:v", "libvpx-vp9");
|
||
|
cmd.push("-crf", String(preset.crf));
|
||
|
cmd.push("-b:v", preset.mbitMax ? `${preset.mbitMax * 1000}k` : "0");
|
||
|
} else preset satisfies never;
|
||
|
|
||
|
if (preset.maxHeight != null) {
|
||
|
cmd.push("-vf", `scale=-2:min(${preset.maxHeight}\\,ih)`);
|
||
|
}
|
||
|
|
||
|
cmd.push("-c:a", "libopus");
|
||
|
cmd.push("-b:a", (preset.audioKbit ?? 192) + "k");
|
||
|
|
||
|
cmd.push("-y");
|
||
|
cmd.push("-f", "hls");
|
||
|
cmd.push("-hls_list_size", "0");
|
||
|
cmd.push("-hls_segment_type", "fmp4");
|
||
|
cmd.push("-hls_time", "2");
|
||
|
cmd.push("-hls_allow_cache", "1");
|
||
|
cmd.push("-hls_fmp4_init_filename", preset.id + ".mp4");
|
||
|
cmd.push(path.join(outbase, preset.id + ".m3u8"));
|
||
|
|
||
|
return cmd;
|
||
|
}
|
||
|
|
||
|
import * as path from "node:path";
|