Release / check-release (push) Successful in 59s
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 1m44s
CI / Build Linux (push) Successful in 2m3s
133 lines
4.2 KiB
Rust
133 lines
4.2 KiB
Rust
// Copyright (C) 2026 Elias Wendland <eliaswendland@pm.me>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 3 exclusively.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
use crate::plugin::Plugin;
|
|
use rust_ffmpeg::FFmpegBuilder;
|
|
use std::io::Write;
|
|
use std::path::Path;
|
|
|
|
pub struct PluginImpl;
|
|
|
|
impl Plugin for PluginImpl {
|
|
fn name(&self) -> &'static str {
|
|
"ffmpeg_audio"
|
|
}
|
|
fn from_formats(&self) -> Vec<&'static str> {
|
|
vec![
|
|
"mp3", "wav", "ogg", "flac", "aac", "m4a", "opus", "wma", "amr", "aiff", "aiff", "au",
|
|
]
|
|
}
|
|
fn to_formats(&self) -> Vec<&'static str> {
|
|
vec![
|
|
"mp3", "wav", "ogg", "flac", "aac", "m4a", "opus", "wma", "amr", "aiff", "aiff", "au",
|
|
]
|
|
}
|
|
fn familiarity(&self, _from: &str, to: &str) -> u8 {
|
|
match to {
|
|
"mp3" | "wav" => 255,
|
|
"flac" | "m4a" | "aac" => 240,
|
|
"ogg" | "opus" => 220,
|
|
"wma" | "amr" => 150,
|
|
"aiff" | "au" => 120,
|
|
_ => 128,
|
|
}
|
|
}
|
|
fn quality(&self, _from: &str, to: &str) -> u8 {
|
|
match to {
|
|
"flac" | "wav" | "aiff" | "au" => 255,
|
|
"opus" | "ogg" | "aac" | "m4a" => 220,
|
|
"mp3" => 200,
|
|
"wma" | "amr" => 150,
|
|
_ => 128,
|
|
}
|
|
}
|
|
fn speed(&self, _from: &str, to: &str) -> u8 {
|
|
match to {
|
|
"wav" | "aiff" | "au" => 255,
|
|
"flac" => 200,
|
|
"mp3" | "aac" | "m4a" | "ogg" => 180,
|
|
"opus" | "wma" | "amr" => 150,
|
|
_ => 128,
|
|
}
|
|
}
|
|
|
|
fn convert(
|
|
&self,
|
|
input: &[u8],
|
|
_from: &str,
|
|
to: &str,
|
|
temp_dir: &Path,
|
|
) -> Result<Vec<u8>, String> {
|
|
let mut temp_in = tempfile::Builder::new()
|
|
.suffix(&format!(".{}", _from))
|
|
.tempfile_in(temp_dir)
|
|
.map_err(|e| e.to_string())?;
|
|
temp_in.write_all(input).map_err(|e| e.to_string())?;
|
|
|
|
let temp_out = tempfile::Builder::new()
|
|
.suffix(&format!(".{}", to))
|
|
.tempfile_in(temp_dir)
|
|
.map_err(|e| e.to_string())?;
|
|
let temp_out_path = temp_out.into_temp_path();
|
|
|
|
let in_path = temp_in.path().to_path_buf();
|
|
|
|
let mut raw_args = vec![];
|
|
match to {
|
|
"mp3" => {
|
|
raw_args.extend(vec!["-c:a", "libmp3lame", "-q:a", "2"]);
|
|
}
|
|
"ogg" => {
|
|
raw_args.extend(vec!["-c:a", "libvorbis", "-q:a", "4"]);
|
|
}
|
|
"flac" => {
|
|
raw_args.extend(vec!["-c:a", "flac"]);
|
|
}
|
|
"aac" | "m4a" => {
|
|
raw_args.extend(vec!["-c:a", "aac", "-b:a", "192k"]);
|
|
}
|
|
"opus" => {
|
|
raw_args.extend(vec!["-c:a", "libopus", "-b:a", "128k"]);
|
|
}
|
|
"wma" => {
|
|
raw_args.extend(vec!["-c:a", "wmav2", "-b:a", "192k"]);
|
|
}
|
|
"amr" => {
|
|
raw_args.extend(vec!["-ar", "8000", "-c:a", "libopencore_amrnb", "-b:a", "12.2k"]);
|
|
}
|
|
"wav" | "aiff" | "au" => {
|
|
raw_args.extend(vec!["-c:a", "pcm_s16le"]);
|
|
}
|
|
_ => {
|
|
raw_args.extend(vec!["-c:a", "copy"]);
|
|
}
|
|
}
|
|
|
|
let rt = tokio::runtime::Runtime::new().map_err(|e| e.to_string())?;
|
|
rt.block_on(async {
|
|
FFmpegBuilder::new()
|
|
.map_err(|e| e.to_string())?
|
|
.input_path(in_path)
|
|
.output_path(temp_out_path.to_path_buf())
|
|
.raw_args(raw_args)
|
|
.overwrite()
|
|
.run()
|
|
.await
|
|
.map_err(|e| e.to_string())
|
|
})?;
|
|
|
|
std::fs::read(&temp_out_path).map_err(|e| e.to_string())
|
|
}
|
|
}
|