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<PresetCategory> = { let mut preset_categories: Vec<PresetCategory> = 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<PresetCategory>) { let mut presets: Vec<Preset> = 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<PresetCategory>) { let mut presets: Vec<Preset> = 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<PresetCategory>) { let mut presets: Vec<Preset> = 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<PresetCategory>) { let mut presets: Vec<Preset> = 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<PresetCategory>) { let mut presets: Vec<Preset> = 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<PresetCategory>) { 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<PresetCategory>) { 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<TranscodeConfig> { 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<TranscodeConfig, Box<dyn std::error::Error>> { 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(), )) } }