use anyhow::{Context, Result};
use gst::prelude::*;
use hls_transcoder::PipelineBuilder;
use std::{
env, fs,
path::{Path, PathBuf},
time::Instant,
};
fn main() -> Result<()> {
let start_time = Instant::now();
let args: Vec<String> = env::args().collect();
if args.len() < 4 {
return Err(anyhow::anyhow!(
"Invalid arguments. Example: mp4_to_hls input.mp4 hls_output variant1 1280 720 1000000"
));
}
let input_file = PathBuf::from(args[1].clone());
let output_dir = PathBuf::from(args[2].clone());
let variant_name = args[3].clone();
let width: i32 = args
.get(4)
.ok_or_else(|| anyhow::anyhow!("Missing width argument"))?
.parse()?;
let height: i32 = args
.get(5)
.ok_or_else(|| anyhow::anyhow!("Missing height argument"))?
.parse()?;
let bitrate: u32 = args
.get(6)
.ok_or_else(|| anyhow::anyhow!("Missing bitrate argument"))?
.parse()?;
validate_input_file(&input_file)?;
create_output_dir(&output_dir, &variant_name)?;
let pipeline_builder = PipelineBuilder::new(
input_file.to_str().unwrap().to_string(),
output_dir.to_str().unwrap().to_string(),
variant_name,
width,
height,
bitrate,
true
);
let pipeline = pipeline_builder
.build()
.context("Failed to build pipeline")?;
let playing_start_time = Instant::now();
pipeline
.set_state(gst::State::Playing)
.context("Failed to set pipeline to playing state")?;
println!(
"Pipeline set to Playing state in {:.2?}",
playing_start_time.elapsed()
);
let bus = pipeline
.bus()
.expect("Failed to retrieve bus from pipeline");
for msg in bus.iter_timed(gst::ClockTime::NONE) {
match msg.view() {
gst::MessageView::Eos(_) => break,
gst::MessageView::Error(err) => return Err(anyhow::anyhow!("Error: {}", err.error())),
_ => (),
}
}
let stopping_start_time = Instant::now();
pipeline.set_state(gst::State::Null)?;
println!("Pipeline set to Null state in {:.2?}", stopping_start_time.elapsed());
println!("Total execution time: {:.2?}", start_time.elapsed());
Ok(())
}
fn validate_input_file(input_file: &Path) -> Result<()> {
if !input_file.exists() {
return Err(anyhow::anyhow!(
"Input file does not exist: {}",
input_file.display()
));
}
Ok(())
}
fn create_output_dir(output_dir: &Path, variant_name: &str) -> Result<()> {
fs::create_dir_all(output_dir.join(variant_name))
.context("Failed to create output directory")?;
Ok(())
}