sitegen/src/file-viewer/transcode-rules.ts

154 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";