fix: fix mpg, mpeg, vob, and amv conversions

amv is weird as hell thanks for that (also i forgot that i could check vertd cause i already fixed them there lol)
This commit is contained in:
Maya 2026-06-08 20:23:05 +03:00
parent 120f6f4780
commit a5b89cf21b
No known key found for this signature in database
3 changed files with 113 additions and 52 deletions

View File

@ -420,7 +420,105 @@ export class FFmpegConverter extends Converter {
let channelsArgs: string[] = [];
let tracksArgs: string[] = [];
let metadataArgs: string[] = [];
let m4aArgs: string[] = [];
const extraArgs: string[] = [];
const checkSettings = () => {
/*
* sanity check settings for certain formats, to prevent conversion failure
*/
const settingsChanged: SettingChange[] = [];
console.log(
`checking settings for compatibility with output format ${to}...`,
);
if (to === ".opus") {
// work around browser stereo+libopus wasm crash
// no idea why its broken like this in the browser only lol
if (settings.channels >= 2) {
channelsArgs = ["-ac", "1"];
settingsChanged.push({
setting: "channels",
oldValue: settings.channels,
newValue: 1,
file: input.name,
});
}
// TODO: surely better way to do this as well :sob:
if (
audioBitrateArgs[1] &&
parseInt(audioBitrateArgs[1], 10) > 256
) {
audioBitrateArgs = ["-b:a", "256k"];
settingsChanged.push({
setting: "bitrate",
oldValue: settings.bitrate,
newValue: 256,
file: input.name,
});
}
} else if (to === ".amv") {
// amv requires mono audio, 32kbps, and 22050 sample rate
// block size is 22050 (sample rate) / fps. max is 8192, so we have to force a higher fps
const amvFps = 3;
const amvBlockSize = Math.floor(22050 / amvFps);
audioBitrateArgs = ["-b:a", "32k"];
sampleRateArgs = ["-ar", "22050"];
channelsArgs = ["-ac", "1"];
extraArgs.push(
"-r",
String(amvFps),
"-block_size",
String(amvBlockSize),
);
settingsChanged.push({
setting: "sampleRate",
oldValue: settings.sampleRate,
newValue: 22050,
file: input.name,
});
settingsChanged.push({
setting: "channels",
oldValue: settings.channels,
newValue: 1,
file: input.name,
});
settingsChanged.push({
setting: "bitrate",
oldValue: settings.bitrate,
newValue: 32,
file: input.name,
});
} else if (to === ".mpg" || to === ".mpeg" || to === ".vob") {
// these formats need to have its bitrate to the power of 2 to convert correctly
const bitrate = parseInt(audioBitrateArgs[1], 10);
const newBitrate = Math.pow(2, Math.round(Math.log2(bitrate)));
audioBitrateArgs = ["-b:a", `${newBitrate}k`];
settingsChanged.push({
setting: "bitrate",
oldValue: settings.bitrate,
newValue: newBitrate,
file: input.name,
});
}
for (const change of settingsChanged) {
this.log(
`changed setting "${change.setting}" from "${change.oldValue}" to "${change.newValue}" for file ${change.file} to prevent conversion failure`,
);
ToastManager.add({
type: "warning",
message: m["workers.warnings.settings_change"]({
setting: change.setting,
oldValue: change.oldValue,
newValue: change.newValue,
file: change.file,
}),
});
}
};
this.log(`keep metadata: ${keepMetadata}`);
if (!keepMetadata) {
@ -522,6 +620,7 @@ export class FFmpegConverter extends Converter {
// video to audio
if (videoFormats.includes(inputFormat)) {
this.log(`Converting video ${input.from} to audio ${to}`);
checkSettings();
return [
"-i",
"input",
@ -532,6 +631,7 @@ export class FFmpegConverter extends Converter {
...sampleRateArgs,
...channelsArgs,
...tracksArgs,
...extraArgs,
"output" + to,
];
}
@ -545,6 +645,8 @@ export class FFmpegConverter extends Converter {
: false;
const codecArgs = toArgs(to, isAlac);
checkSettings();
if (hasAlbumArt) {
this.log("Using album art as video background");
return avWithArt(
@ -554,6 +656,7 @@ export class FFmpegConverter extends Converter {
audioBitrateArgs,
sampleRateArgs,
channelsArgs,
extraArgs,
);
} else {
this.log("Using solid color background");
@ -564,6 +667,7 @@ export class FFmpegConverter extends Converter {
audioBitrateArgs,
sampleRateArgs,
channelsArgs,
extraArgs,
);
}
}
@ -571,60 +675,13 @@ export class FFmpegConverter extends Converter {
// audio to audio
this.log(`Converting audio ${input.from} to audio ${to}`);
const { audio: audioCodec } = getCodecs(to, isAlac);
if (m4a && keepMetadata) m4aArgs = ["-c:v", "copy"]; // for album art
if (m4a && keepMetadata) extraArgs.push("-c:v", "copy"); // for album art
/*
* sanity check settings for certain formats, to prevent conversion failure
*/
const settingsChanged: SettingChange[] = [];
if (to === ".opus") {
// work around browser stereo+libopus wasm crash
// no idea why its broken like this in the browser only lol
if (settings.channels >= 2) {
channelsArgs = ["-ac", "1"];
settingsChanged.push({
setting: "channels",
oldValue: settings.channels,
newValue: 1,
file: input.name,
});
}
// TODO: surely better way to do this as well :sob:
if (
audioBitrateArgs[1] &&
parseInt(audioBitrateArgs[1], 10) > 256
) {
audioBitrateArgs = ["-b:a", "256k"];
settingsChanged.push({
setting: "bitrate",
oldValue: settings.bitrate,
newValue: 256,
file: input.name,
});
}
}
for (const change of settingsChanged) {
this.log(
`changed setting "${change.setting}" from "${change.oldValue}" to "${change.newValue}" for file ${change.file} to prevent conversion failure`,
);
ToastManager.add({
type: "warning",
message: m["workers.warnings.settings_change"]({
setting: change.setting,
oldValue: change.oldValue,
newValue: change.newValue,
file: change.file,
}),
});
}
checkSettings();
return [
"-i",
"input",
...m4aArgs,
"-c:a",
audioCodec,
...metadataArgs,
@ -632,6 +689,7 @@ export class FFmpegConverter extends Converter {
...sampleRateArgs,
...channelsArgs,
...tracksArgs,
...extraArgs,
"-strict",
"experimental",
"output" + to,
@ -724,7 +782,6 @@ const handleSpecialOutput = async (
".qoa",
);
}
// if (whatever other formats need special parsing)
return null;

View File

@ -56,6 +56,7 @@ export const avWithArt = (
audioBitrateArgs: string[],
sampleRateArgs: string[],
channelsArgs: string[],
extraArgs: string[],
): string[] => {
return [
"-loop",
@ -80,6 +81,7 @@ export const avWithArt = (
...audioBitrateArgs,
...sampleRateArgs,
...channelsArgs,
...extraArgs,
"output" + to,
];
};
@ -92,6 +94,7 @@ export const avWithBg = (
audioBitrateArgs: string[],
sampleRateArgs: string[],
channelsArgs: string[],
extraArgs: string[],
): string[] => {
return [
"-f",
@ -114,6 +117,7 @@ export const avWithBg = (
...audioBitrateArgs,
...sampleRateArgs,
...channelsArgs,
...extraArgs,
"output" + to,
];
};

View File

@ -44,7 +44,7 @@ export const detectAudioBitrate = async (
return await ffprobeValue(ffmpeg, args, (s) => {
const n = parseInt(s, 10);
return Number.isFinite(n) ? Math.round(n / 1000) : null;
return Number.isFinite(n) ? Math.floor(n / 1000) : null;
});
};