feat: audio to video for new formats

This commit is contained in:
Maya 2025-07-28 21:01:20 +03:00
parent 9cb4d6f5e9
commit 77914de25d
No known key found for this signature in database
1 changed files with 88 additions and 16 deletions

View File

@ -17,6 +17,19 @@ const videoFormats = [
"mts", "mts",
"m2ts", "m2ts",
"wmv", "wmv",
"mpg",
"mpeg",
"flv",
"f4v",
"vob",
"m4v",
"3gp",
"3g2",
"mxf",
"ogv",
"rm",
"rmvb",
"divx",
]; ];
export class FFmpegConverter extends Converter { export class FFmpegConverter extends Converter {
@ -165,6 +178,7 @@ export class FFmpegConverter extends Converter {
["converters", this.name], ["converters", this.name],
"Using album art as video background", "Using album art as video background",
); );
const codecArgs = toArgs(to);
return [ return [
"-loop", "-loop",
"1", "1",
@ -174,18 +188,17 @@ export class FFmpegConverter extends Converter {
"input", "input",
"-vf", "-vf",
"scale=trunc(iw/2)*2:trunc(ih/2)*2", "scale=trunc(iw/2)*2:trunc(ih/2)*2",
"-c:a",
"aac",
"-shortest", "-shortest",
"-pix_fmt", "-pix_fmt",
"yuv420p", "yuv420p",
"-r", "-r",
"1", "1",
...toArgs(to), ...codecArgs,
"output" + to, "output" + to,
]; ];
} else { } else {
log(["converters", this.name], "Using solid color background"); log(["converters", this.name], "Using solid color background");
const codecArgs = toArgs(to);
return [ return [
"-f", "-f",
"lavfi", "lavfi",
@ -193,14 +206,12 @@ export class FFmpegConverter extends Converter {
"color=c=black:s=640x480:rate=1", "color=c=black:s=640x480:rate=1",
"-i", "-i",
"input", "input",
"-c:a",
"aac",
"-shortest", "-shortest",
"-pix_fmt", "-pix_fmt",
"yuv420p", "yuv420p",
"-r", "-r",
"1", "1",
...toArgs(to), ...codecArgs,
"output" + to, "output" + to,
]; ];
} }
@ -221,6 +232,8 @@ export class FFmpegConverter extends Converter {
"0:1", "0:1",
"-c:v", "-c:v",
"copy", "copy",
"-update",
"1",
"cover.jpg", "cover.jpg",
]) ])
) { ) {
@ -239,6 +252,8 @@ export class FFmpegConverter extends Converter {
"-an", "-an",
"-c:v", "-c:v",
"copy", "copy",
"-update",
"1",
"cover.jpg", "cover.jpg",
]) ])
) { ) {
@ -276,9 +291,10 @@ export class FFmpegConverter extends Converter {
// i hate you SO much. // i hate you SO much.
// - love, maddie // - love, maddie
const toArgs = (ext: string): string[] => { const toArgs = (ext: string): string[] => {
const encoder = getEncoder(ext); const codecs = getCodecs(ext);
const args = ["-c:v", encoder]; const args = ["-c:v", codecs.video];
switch (encoder) {
switch (codecs.video) {
case "libx264": { case "libx264": {
args.push( args.push(
"-preset", "-preset",
@ -292,24 +308,80 @@ const toArgs = (ext: string): string[] => {
} }
case "libvpx": { case "libvpx": {
args.push("-c:v", "libvpx-vp9", "-c:a", "libvorbis"); args.push("-c:v", "libvpx-vp9");
break;
}
case "mpeg4": {
// for avi and divx
break;
}
case "mpeg2video": {
// for mpeg, mpg, vob, mxf
if (ext === ".mxf") args.push("-ar", "48000"); // force 48kHz sample rate
break;
}
case "libtheora": {
// for ogv
break;
}
case "wmv2": {
// for wmv
break; break;
} }
} }
args.push("-c:a", codecs.audio);
if (codecs.audio === "aac") args.push("-strict", "experimental");
if (ext === ".divx") args.unshift("-f", "avi");
if (ext === ".mxf") args.push("-strict", "unofficial");
return args; return args;
}; };
const getEncoder = (ext: string): string => { const getCodecs = (ext: string): { video: string; audio: string } => {
switch (ext) { switch (ext) {
case ".mkv":
case ".mp4": case ".mp4":
case ".avi": case ".mkv":
case ".mov": case ".mov":
return "libx264"; case ".mts":
case ".ts":
case ".m2ts":
case ".flv":
case ".f4v":
case ".m4v":
case ".3gp":
case ".3g2":
return { video: "libx264", audio: "aac" };
case ".wmv":
return { video: "wmv2", audio: "wmav2" };
case ".webm": case ".webm":
return "libvpx"; case ".ogv":
return {
video: ext === ".webm" ? "libvpx" : "libtheora",
audio: "libvorbis",
};
case ".avi":
case ".divx":
return { video: "mpeg4", audio: "libmp3lame" };
case ".mpg":
case ".mpeg":
case ".vob":
return { video: "mpeg2video", audio: "mp2" };
case ".mxf":
return { video: "mpeg2video", audio: "pcm_s16le" };
default: default:
return "copy"; return { video: "libx264", audio: "aac" };
} }
}; };