bumblebee/src/main.rs

143 lines
4.9 KiB
Rust

#[macro_use]
extern crate simple_log;
use std::env;
use std::path::PathBuf;
use simple_log::LogConfigBuilder;
use renice::renice;
use transcode::job::TranscodeJob;
use crate::configuration::Config;
mod configuration;
mod files;
mod ffmpeg;
mod renice;
mod transcode;
mod error;
fn main() {
let config = configuration::Config::from_file(&env::var("CONFIG").unwrap_or(String::from("./config.toml")));
setup_logger(&config);
trace!("Config: {:#?}", &config);
debug!("commit: {}", env!("GIT_COMMIT_HASH"));
debug!("tag: {}", env!("GIT_TAG"));
let input_files = files::get_files(&config.files.input_path)
.into_iter()
.filter(|path| {
let path = path.to_str().unwrap();
config.files.include.iter().any(|include| path.contains(include))
})
.collect::<Vec<_>>();
info!("Found {} file(s) to be processed.", input_files.len());
let success_count = start_transcode_run(&input_files, &config);
info!("Finished processing {}/{} file(s).", success_count, input_files.len());
}
fn start_transcode_run(input_files: &Vec<PathBuf>, config: &Config) -> i32 {
let mut success_count = 0;
for file in input_files {
let fail = |job: &TranscodeJob, remarks: &str| {
error!("Failed to process file {}: {}", job.input, remarks);
};
let mut output_path = if let Some(keep_directory_structure) = config.files.keep_directory_structure {
if keep_directory_structure {
let mut output_path = PathBuf::from(&config.files.output_path);
output_path.push(file.strip_prefix(&config.files.input_path).unwrap());
output_path
} else {
PathBuf::from(&config.files.output_path)
.join(file.file_name().unwrap())
}
} else {
PathBuf::from(&config.files.output_path)
.join(file.file_name().unwrap())
};
output_path.set_extension(&config.ffmpeg.output.format);
let job = TranscodeJob::new(
file.to_str().unwrap(),
output_path.to_str().unwrap(),
);
// check if overwriting
if job.check_if_exists() {
if config.ffmpeg.overwrite.unwrap_or(false) {
info!("Overwriting file {}.", job.input);
} else {
info!("Skipping file {} as it already exists.", job.input);
continue;
}
}
info!("Processing file {}.", job.input);
let mut child = match job.run(&config.ffmpeg) {
Ok(child) => child,
Err(e) => {
fail(&job, &format!("Failed to start ffmpeg process: {}", e));
continue;
}
};
if let Some(process) = &config.ffmpeg.process {
if (process.niceness.unwrap_or(0)) > 0 {
if let Err(e) = renice(child.id(), process.niceness.unwrap_or(0)) {
error!("Failed to renice ffmpeg process: {}", e);
}
}
}
if let Err(e) = child.wait() {
fail(&job, &format!("Failed to wait for ffmpeg process: {}", e));
continue;
}
if let Some(cleanup) = &config.files.cleanup {
if !cleanup.enabled { () }
match cleanup.original_cleanup_behavior {
configuration::ConfigFilesCleanupOriginalBehavior::delete => {
if let Err(e) = std::fs::remove_file(&job.input) {
error!("Failed to delete original file {}: {}", job.input, e);
}
},
configuration::ConfigFilesCleanupOriginalBehavior::archive => {
let mut archive_path = PathBuf::from(&cleanup.archive.path);
archive_path.push(job.input.strip_prefix(&config.files.input_path).unwrap());
if let Err(e) = std::fs::create_dir_all(archive_path.parent().unwrap()) {
error!("Failed to create archive directory {}: {}", archive_path.parent().unwrap().to_str().unwrap(), e);
}
if let Err(e) = std::fs::rename(&job.input, &archive_path) {
error!("Failed to archive original file {}: {}", job.input, e);
}
},
configuration::ConfigFilesCleanupOriginalBehavior::keep => (),
}
}
info!("Finished processing file {}.", job.input);
success_count += 1;
}
success_count
}
fn setup_logger(config: &configuration::Config) {
let log_config = LogConfigBuilder::builder()
.path("backups.log")
.size(10 * 1000)
.roll_count(10)
.time_format("%Y-%m-%d %H:%M:%S")
.level(if config.is_debug() { "trace" } else { "info" })
.output_file()
.output_console()
.build();
simple_log::new(log_config).unwrap();
}