feat: implement robust format identification, plugin availability checks, and automatic conversion path rerouting on failure
Release / check-release (push) Successful in 16s
Release / build_gnu (push) Skipped
Release / build_musl (push) Skipped
Release / build_windows (push) Skipped
Release / package_gnu (deb) (push) Skipped
Release / package_gnu (rpm) (push) Skipped
Release / package_musl (deb) (push) Skipped
Release / package_musl (rpm) (push) Skipped
Release / publish-release (push) Skipped
CI / Test (push) Successful in 1m52s
CI / Build Linux (push) Successful in 2m0s

This commit is contained in:
Elias Wendland
2026-07-16 14:37:21 +02:00
parent a372937854
commit d3b7d7a18f
8 changed files with 244 additions and 97 deletions
+115 -21
View File
@@ -23,47 +23,63 @@ impl Plugin for PluginImpl {
fn name(&self) -> &'static str {
"ffmpeg_video"
}
fn from_formats(&self) -> Vec<&'static str> {
vec!["mp4", "webm", "mkv", "avi", "mov", "wmv", "flv", "gif"]
vec![
"mp4", "webm", "mkv", "avi", "mov", "wmv", "flv", "gif", "m4v", "3gp", "ts", "m2ts",
"vob", "mpg", "mpeg", "mxf", "ogv", "apng", "webp",
]
}
fn to_formats(&self) -> Vec<&'static str> {
vec!["mp4", "webm", "mkv", "avi", "mov", "wmv", "flv", "gif"]
vec![
"mp4", "webm", "mkv", "avi", "mov", "wmv", "flv", "gif", "m4v", "3gp", "ts", "m2ts",
"vob", "mpg", "mpeg", "mxf", "ogv", "apng", "webp",
]
}
fn is_available(&self) -> bool {
std::process::Command::new("ffmpeg")
.arg("-version")
.output()
.is_ok()
}
fn familiarity(&self, _from: &str, to: &str) -> u8 {
match to {
"mp4" | "gif" => 255,
"mov" => 240,
"mov" | "m4v" => 240,
"webm" => 220,
"mkv" => 180,
"wmv" => 160,
"flv" => 120,
"avi" => 100,
"wmv" | "mpg" | "mpeg" => 160,
"flv" | "avi" | "3gp" | "vob" => 120,
"ts" | "m2ts" | "mxf" | "ogv" | "apng" | "webp" => 100,
_ => 128,
}
}
fn quality(&self, _from: &str, to: &str) -> u8 {
match to {
"mkv" => 250,
"mov" => 250,
"mp4" => 240,
"mkv" | "mxf" | "ts" | "m2ts" => 250,
"mov" | "mp4" | "m4v" => 240,
"webm" => 210,
"wmv" => 200,
"flv" => 180,
"avi" => 150,
"gif" => 80,
"wmv" | "mpg" | "mpeg" | "vob" => 200,
"flv" | "avi" | "ogv" | "3gp" => 150,
"gif" | "apng" => 100,
"webp" => 50,
_ => 200,
}
}
fn speed(&self, _from: &str, to: &str) -> u8 {
match to {
"mp4" => 220,
"mov" => 220,
"mkv" => 200,
"flv" => 190,
"avi" => 180,
"mp4" | "mov" | "m4v" => 220,
"mkv" | "mpg" | "mpeg" | "ts" | "m2ts" | "mxf" | "vob" => 200,
"flv" | "avi" | "3gp" | "ogv" => 180,
"wmv" => 170,
"gif" => 150,
"webm" => 100,
"gif" | "apng" => 150,
"webp" => 100,
"webm" => 50,
_ => 150,
}
}
@@ -91,7 +107,7 @@ impl Plugin for PluginImpl {
let mut raw_args = vec![];
match to {
"mp4" | "mkv" | "mov" => {
"mp4" | "mkv" | "mov" | "m4v" => {
raw_args.extend(vec![
"-c:v", "libx264", "-crf", "23", "-c:a", "aac", "-pix_fmt", "yuv420p",
]);
@@ -120,9 +136,87 @@ impl Plugin for PluginImpl {
"libmp3lame",
]);
}
"wmv" => {
raw_args.extend(vec![
"-c:v", "wmv2", "-b:v", "1024k", "-c:a", "wmav2", "-b:a", "128k",
]);
}
"flv" => {
raw_args.extend(vec![
"-c:v",
"flv1",
"-b:v",
"800k",
"-c:a",
"libmp3lame",
"-b:a",
"128k",
]);
}
"ts" | "m2ts" | "mpg" | "mpeg" | "vob" => {
raw_args.extend(vec![
"-c:v",
"mpeg2video",
"-qscale:v",
"2",
"-c:a",
"mp2",
"-b:a",
"192k",
]);
}
"mxf" => {
raw_args.extend(vec![
"-c:v",
"mpeg2video",
"-qscale:v",
"2",
"-c:a",
"pcm_s16le",
]);
}
"ogv" => {
raw_args.extend(vec![
"-c:v",
"libtheora",
"-qscale:v",
"6",
"-c:a",
"libvorbis",
"-qscale:a",
"4",
]);
}
"3gp" => {
raw_args.extend(vec![
"-c:v",
"h263",
"-s",
"352x288",
"-c:a",
"libopencore_amrnb",
"-ar",
"8000",
]);
}
"gif" => {
raw_args.extend(vec!["-vf", "fps=15,scale=320:-1:flags=lanczos"]);
}
"webp" => {
raw_args.extend(vec![
"-c:v",
"libwebp",
"-lossless",
"0",
"-qscale",
"75",
"-loop",
"0",
]);
}
"apng" => {
raw_args.extend(vec!["-plays", "0"]);
}
_ => {
raw_args.extend(vec!["-qscale:v", "3"]);
}