diff --git a/src/args.rs b/src/args.rs index 87a48da..9f5ec3e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -17,4 +17,5 @@ pub enum Commands { Transcode(commands::transcode::TranscodeCommandArgs), Copy(commands::copy::CopyCommandArgs), Tags(commands::tags::TagsArgs), + Presets(commands::presets::PresetsArgs), } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index f63d373..3aad189 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -4,3 +4,4 @@ pub mod genhtml; pub mod process; pub mod tags; pub mod transcode; +pub mod presets; diff --git a/src/commands/presets.rs b/src/commands/presets.rs new file mode 100644 index 0000000..eadf471 --- /dev/null +++ b/src/commands/presets.rs @@ -0,0 +1,62 @@ +use crate::args::CLIArgs; + +#[derive(Debug, Clone, clap::Args)] +pub struct PresetsArgs { + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Debug, Clone, clap::Subcommand)] +pub enum PresetsCommands { + Print, + Dump(PresetsDumpCommandArgs), +} + +#[derive(Debug, Clone, clap::Args)] +pub struct PresetsDumpCommandArgs { + pub preset: String, + #[clap(long, value_enum, default_value_t=DumpFormat::YAML)] + pub format: DumpFormat, +} + +#[derive(Debug, Clone, clap::ValueEnum)] +pub enum DumpFormat { + YAML, + JSON, +} + +impl Default for DumpFormat { + fn default() -> Self { + Self::YAML + } +} + +pub fn presets_command( + _args: CLIArgs, + presets_args: &PresetsArgs, +) -> Result<(), Box> { + let command = presets_args.command.to_owned(); + match command { + None | Some(PresetsCommands::Print) => crate::utils::transcoder::presets::print_presets(), + Some(PresetsCommands::Dump(x)) => { + let preset = match crate::utils::transcoder::presets::get_preset(x.preset) { + Some(preset) => preset, + None => { + println!("invalid preset specified"); + std::process::exit(1); + }, + }; + + match x.format { + DumpFormat::YAML => { + println!("{}", serde_yaml::to_string(&preset)?) + } + DumpFormat::JSON => { + println!("{}", serde_json::to_string_pretty(&preset)?) + } + } + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index c62f4a7..744786a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,5 +29,8 @@ fn main() -> Result<(), Box> { Commands::Tags(subcommand_args) => { return commands::tags::tags_command(cli, &subcommand_args); } + Commands::Presets(subcommand_args) => { + return commands::presets::presets_command(cli, &subcommand_args); + } } } diff --git a/src/utils/transcoder/presets.rs b/src/utils/transcoder/presets.rs deleted file mode 100644 index bf8849a..0000000 --- a/src/utils/transcoder/presets.rs +++ /dev/null @@ -1,217 +0,0 @@ -use lazy_static::lazy_static; -use string_error::into_err; - -use crate::utils::transcoder::types::Preset; -use crate::utils::transcoder::types::PresetCategory; -use crate::utils::transcoder::types::TranscodeConfig; - -lazy_static! { - #[derive(Debug)] - pub static ref TRANSCODE_CONFIGS: Vec = { - let mut preset_categories: Vec = Vec::new(); - - add_mp3_presets(&mut preset_categories); - add_opus_presets(&mut preset_categories); - add_vorbis_presets(&mut preset_categories); - add_g726_presets(&mut preset_categories); - add_speex_presets(&mut preset_categories); - add_flac_preset(&mut preset_categories); - add_wav_preset(&mut preset_categories); - - preset_categories - }; -} - -fn add_mp3_presets(preset_categories: &mut Vec) { - let mut presets: Vec = Vec::new(); - for bitrate in [ - 8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, - ] { - presets.push(Preset { - name: format!("mp3-{}k", bitrate).to_string(), - config: TranscodeConfig { - file_extension: Some("mp3".to_string()), - encoder: Some("libmp3lame".to_string()), - container: Some("mp3".to_string()), - bitrate: Some(format!("{}k", bitrate).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - for quality in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] { - presets.push(Preset { - name: format!("mp3-v{}", quality).to_string(), - config: TranscodeConfig { - file_extension: Some("mp3".to_string()), - encoder: Some("libmp3lame".to_string()), - container: Some("mp3".to_string()), - quality: Some(format!("{}", quality).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - preset_categories.push(PresetCategory { - name: "mp3".to_string(), - presets, - }); -} - -fn add_opus_presets(preset_categories: &mut Vec) { - let mut presets: Vec = Vec::new(); - for bitrate in [16, 24, 32, 64, 96, 128, 256] { - presets.push(Preset { - name: format!("opus-{}k", bitrate).to_string(), - config: TranscodeConfig { - file_extension: Some("opus".to_string()), - encoder: Some("libopus".to_string()), - container: Some("ogg".to_string()), - bitrate: Some(format!("{}k", bitrate).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - preset_categories.push(PresetCategory { - name: "opus".to_string(), - presets, - }); -} - -fn add_vorbis_presets(preset_categories: &mut Vec) { - let mut presets: Vec = Vec::new(); - for quality in [-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { - presets.push(Preset { - name: format!("vorbis-v{}", quality).to_string(), - config: TranscodeConfig { - file_extension: Some("ogg".to_string()), - encoder: Some("libvorbis".to_string()), - container: Some("ogg".to_string()), - quality: Some(format!("{}", quality).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - preset_categories.push(PresetCategory { - name: "vorbis".to_string(), - presets, - }); -} - -fn add_g726_presets(preset_categories: &mut Vec) { - let mut presets: Vec = Vec::new(); - for bitrate in [16, 24, 32, 64, 96, 128, 256] { - presets.push(Preset { - name: format!("g726-{}k", bitrate).to_string(), - config: TranscodeConfig { - file_extension: Some("mka".to_string()), - encoder: Some("g726".to_string()), - container: Some("matroska".to_string()), - sample_rate: Some("8000".to_string()), - channels: Some("1".to_string()), - bitrate: Some(format!("{}k", bitrate).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - preset_categories.push(PresetCategory { - name: "g726".to_string(), - presets, - }); -} - -fn add_speex_presets(preset_categories: &mut Vec) { - let mut presets: Vec = Vec::new(); - for quality in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { - presets.push(Preset { - name: format!("speex-q{}", quality).to_string(), - config: TranscodeConfig { - file_extension: Some("ogg".to_string()), - encoder: Some("libspeex".to_string()), - container: Some("ogg".to_string()), - quality: Some(format!("{}", quality).to_string()), - ..TranscodeConfig::default() - }, - }) - } - - preset_categories.push(PresetCategory { - name: "speex".to_string(), - presets, - }); -} - -fn add_flac_preset(preset_categories: &mut Vec) { - preset_categories.push(PresetCategory { - name: "flac".to_string(), - presets: Vec::from([Preset { - name: "flac".to_string(), - config: TranscodeConfig { - encoder: Some("flac".to_string()), - container: Some("flac".to_string()), - file_extension: Some("flac".to_string()), - ..TranscodeConfig::default() - }, - }]), - }) -} - -fn add_wav_preset(preset_categories: &mut Vec) { - preset_categories.push(PresetCategory { - name: "wav".to_string(), - presets: Vec::from([Preset { - name: "wav".to_string(), - config: TranscodeConfig { - container: Some("wav".to_string()), - file_extension: Some("wav".to_string()), - ..TranscodeConfig::default() - }, - }]), - }) -} - -pub fn print_presets() { - for category in TRANSCODE_CONFIGS.iter() { - println!("Category {}:", category.name); - for preset in category.presets.iter() { - println!("- {}", preset.name) - } - } -} - -pub fn get_preset(name: String) -> Option { - for category in TRANSCODE_CONFIGS.iter() { - for preset in category.presets.iter() { - if preset.name == name { - return Some(preset.config.clone()); - } - } - } - - None -} - -pub fn transcode_preset_or_config( - preset_name: Option<&String>, - config_path: Option<&String>, -) -> Result> { - if let Some(preset_name) = preset_name { - let preset_config = get_preset(preset_name.to_string()); - - match preset_config { - Some(config) => Ok(config), - None => Err(into_err("invalid preset name".to_string())), - } - } else if let Some(config_path) = config_path { - let config = TranscodeConfig::load(config_path.to_string())?; - - Ok(config) - } else { - Err(into_err( - "please provide a transcode config or preset".to_string(), - )) - } -} diff --git a/src/utils/transcoder/presets/flac.rs b/src/utils/transcoder/presets/flac.rs new file mode 100644 index 0000000..cb79e2d --- /dev/null +++ b/src/utils/transcoder/presets/flac.rs @@ -0,0 +1,18 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_preset(preset_categories: &mut Vec) { + preset_categories.push(PresetCategory { + name: "flac".to_string(), + presets: Vec::from([Preset { + name: "flac".to_string(), + config: TranscodeConfig { + encoder: Some("flac".to_string()), + container: Some("flac".to_string()), + file_extension: Some("flac".to_string()), + ..TranscodeConfig::default() + }, + }]), + }) +} \ No newline at end of file diff --git a/src/utils/transcoder/presets/g726.rs b/src/utils/transcoder/presets/g726.rs new file mode 100644 index 0000000..9cc7ccf --- /dev/null +++ b/src/utils/transcoder/presets/g726.rs @@ -0,0 +1,26 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_presets(preset_categories: &mut Vec) { + let mut presets: Vec = Vec::new(); + for bitrate in [16, 24, 32, 64, 96, 128, 256] { + presets.push(Preset { + name: format!("g726-{}k", bitrate).to_string(), + config: TranscodeConfig { + file_extension: Some("mka".to_string()), + encoder: Some("g726".to_string()), + container: Some("matroska".to_string()), + sample_rate: Some("8000".to_string()), + channels: Some("1".to_string()), + bitrate: Some(format!("{}k", bitrate).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + preset_categories.push(PresetCategory { + name: "g726".to_string(), + presets, + }); +} \ No newline at end of file diff --git a/src/utils/transcoder/presets/mod.rs b/src/utils/transcoder/presets/mod.rs new file mode 100644 index 0000000..59fab65 --- /dev/null +++ b/src/utils/transcoder/presets/mod.rs @@ -0,0 +1,73 @@ +use lazy_static::lazy_static; +use string_error::into_err; + +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +mod mp3; +mod opus; +mod vorbis; +mod g726; +mod speex; +mod flac; +mod wav; + +lazy_static! { + #[derive(Debug)] + pub static ref TRANSCODE_CONFIGS: Vec = { + let mut preset_categories: Vec = Vec::new(); + + mp3::add_presets(&mut preset_categories); + opus::add_presets(&mut preset_categories); + vorbis::add_presets(&mut preset_categories); + g726::add_presets(&mut preset_categories); + speex::add_presets(&mut preset_categories); + flac::add_preset(&mut preset_categories); + wav::add_preset(&mut preset_categories); + + preset_categories + }; +} + +pub fn print_presets() { + for category in TRANSCODE_CONFIGS.iter() { + println!("Category {}:", category.name); + for preset in category.presets.iter() { + println!("- {}", preset.name) + } + } +} + +pub fn get_preset(name: String) -> Option { + for category in TRANSCODE_CONFIGS.iter() { + for preset in category.presets.iter() { + if preset.name == name { + return Some(preset.config.clone()); + } + } + } + + None +} + +pub fn transcode_preset_or_config( + preset_name: Option<&String>, + config_path: Option<&String>, +) -> Result> { + if let Some(preset_name) = preset_name { + let preset_config = get_preset(preset_name.to_string()); + + match preset_config { + Some(config) => Ok(config), + None => Err(into_err("invalid preset name".to_string())), + } + } else if let Some(config_path) = config_path { + let config = TranscodeConfig::load(config_path.to_string())?; + + Ok(config) + } else { + Err(into_err( + "please provide a transcode config or preset".to_string(), + )) + } +} diff --git a/src/utils/transcoder/presets/mp3.rs b/src/utils/transcoder/presets/mp3.rs new file mode 100644 index 0000000..779eea3 --- /dev/null +++ b/src/utils/transcoder/presets/mp3.rs @@ -0,0 +1,39 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_presets(preset_categories: &mut Vec) { + let mut presets: Vec = Vec::new(); + for bitrate in [ + 8, 16, 24, 32, 40, 48, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, + ] { + presets.push(Preset { + name: format!("mp3-{}k", bitrate).to_string(), + config: TranscodeConfig { + file_extension: Some("mp3".to_string()), + encoder: Some("libmp3lame".to_string()), + container: Some("mp3".to_string()), + bitrate: Some(format!("{}k", bitrate).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + for quality in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] { + presets.push(Preset { + name: format!("mp3-v{}", quality).to_string(), + config: TranscodeConfig { + file_extension: Some("mp3".to_string()), + encoder: Some("libmp3lame".to_string()), + container: Some("mp3".to_string()), + quality: Some(format!("{}", quality).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + preset_categories.push(PresetCategory { + name: "mp3".to_string(), + presets, + }); +} \ No newline at end of file diff --git a/src/utils/transcoder/presets/opus.rs b/src/utils/transcoder/presets/opus.rs new file mode 100644 index 0000000..23768cd --- /dev/null +++ b/src/utils/transcoder/presets/opus.rs @@ -0,0 +1,24 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_presets(preset_categories: &mut Vec) { + let mut presets: Vec = Vec::new(); + for bitrate in [16, 24, 32, 64, 96, 128, 256] { + presets.push(Preset { + name: format!("opus-{}k", bitrate).to_string(), + config: TranscodeConfig { + file_extension: Some("opus".to_string()), + encoder: Some("libopus".to_string()), + container: Some("ogg".to_string()), + bitrate: Some(format!("{}k", bitrate).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + preset_categories.push(PresetCategory { + name: "opus".to_string(), + presets, + }); +} \ No newline at end of file diff --git a/src/utils/transcoder/presets/speex.rs b/src/utils/transcoder/presets/speex.rs new file mode 100644 index 0000000..2343e47 --- /dev/null +++ b/src/utils/transcoder/presets/speex.rs @@ -0,0 +1,24 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_presets(preset_categories: &mut Vec) { + let mut presets: Vec = Vec::new(); + for quality in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { + presets.push(Preset { + name: format!("speex-q{}", quality).to_string(), + config: TranscodeConfig { + file_extension: Some("ogg".to_string()), + encoder: Some("libspeex".to_string()), + container: Some("ogg".to_string()), + quality: Some(format!("{}", quality).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + preset_categories.push(PresetCategory { + name: "speex".to_string(), + presets, + }); +} diff --git a/src/utils/transcoder/presets/vorbis.rs b/src/utils/transcoder/presets/vorbis.rs new file mode 100644 index 0000000..812eb9a --- /dev/null +++ b/src/utils/transcoder/presets/vorbis.rs @@ -0,0 +1,24 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + +pub fn add_presets(preset_categories: &mut Vec) { + let mut presets: Vec = Vec::new(); + for quality in [-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { + presets.push(Preset { + name: format!("vorbis-v{}", quality).to_string(), + config: TranscodeConfig { + file_extension: Some("ogg".to_string()), + encoder: Some("libvorbis".to_string()), + container: Some("ogg".to_string()), + quality: Some(format!("{}", quality).to_string()), + ..TranscodeConfig::default() + }, + }) + } + + preset_categories.push(PresetCategory { + name: "vorbis".to_string(), + presets, + }); +} \ No newline at end of file diff --git a/src/utils/transcoder/presets/wav.rs b/src/utils/transcoder/presets/wav.rs new file mode 100644 index 0000000..48c169c --- /dev/null +++ b/src/utils/transcoder/presets/wav.rs @@ -0,0 +1,18 @@ +use crate::utils::transcoder::types::Preset; +use crate::utils::transcoder::types::PresetCategory; +use crate::utils::transcoder::types::TranscodeConfig; + + +pub fn add_preset(preset_categories: &mut Vec) { + preset_categories.push(PresetCategory { + name: "wav".to_string(), + presets: Vec::from([Preset { + name: "wav".to_string(), + config: TranscodeConfig { + container: Some("wav".to_string()), + file_extension: Some("wav".to_string()), + ..TranscodeConfig::default() + }, + }]), + }) +} \ No newline at end of file