use super::VideoPipeline; #[derive(Debug, Clone)] pub struct PlaybackPlan { pub video_pipeline: VideoPipeline, pub audio_streams: Vec, pub duration_seconds: Option, pub segment_seconds: u8, } impl PlaybackPlan { pub fn live_dash( video_pipeline: VideoPipeline, audio_streams: Vec, duration_seconds: Option, ) -> Self { Self { video_pipeline, audio_streams, duration_seconds, segment_seconds: 2, } } pub fn audio_count(&self) -> usize { self.audio_streams.len() } pub fn ffmpeg_output_args(&self) -> Vec { let mut args = vec!["-map".into(), "0:v:0".into()]; args.extend(self.video_pipeline.ffmpeg_args(self.segment_seconds)); for stream in &self.audio_streams { args.extend(["-map".into(), format!("0:{stream}")]); } if !self.audio_streams.is_empty() { args.extend([ "-c:a".into(), "aac".into(), "-profile:a".into(), "aac_low".into(), "-b:a".into(), "192k".into(), "-ac".into(), "2".into(), ]); } let mut adaptation_sets = vec!["id=0,streams=0".to_owned()]; adaptation_sets.extend( (1..=self.audio_streams.len()).map(|output| format!("id={output},streams={output}")), ); args.extend([ "-sn".into(), "-f".into(), "dash".into(), "-seg_duration".into(), self.segment_seconds.to_string(), "-update_period".into(), "1".into(), "-use_template".into(), "1".into(), "-use_timeline".into(), "1".into(), "-window_size".into(), "0".into(), "-extra_window_size".into(), "0".into(), "-adaptation_sets".into(), adaptation_sets.join(" "), "manifest.mpd".into(), ]); args } } #[cfg(test)] mod tests { use super::{PlaybackPlan, VideoPipeline}; #[test] fn live_profile_copies_video_and_encodes_audio_to_aac() { let args = PlaybackPlan::live_dash(VideoPipeline::Copy, vec![1, 3], Some(120.0)) .ffmpeg_output_args(); assert!(args.windows(2).any(|pair| pair == ["-c:v", "copy"])); assert!(args.windows(2).any(|pair| pair == ["-c:a", "aac"])); assert!(args.windows(2).any(|pair| pair == ["-ac", "2"])); assert!(args.windows(2).any(|pair| pair == ["-map", "0:1"])); assert!(args.windows(2).any(|pair| pair == ["-map", "0:3"])); assert!(args.windows(2).any(|pair| { pair == [ "-adaptation_sets", "id=0,streams=0 id=1,streams=1 id=2,streams=2", ] })); } }