96 lines
2.9 KiB
Rust
96 lines
2.9 KiB
Rust
use super::VideoPipeline;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PlaybackPlan {
|
|
pub video_pipeline: VideoPipeline,
|
|
pub audio_streams: Vec<u32>,
|
|
pub duration_seconds: Option<f64>,
|
|
pub segment_seconds: u8,
|
|
}
|
|
|
|
impl PlaybackPlan {
|
|
pub fn live_dash(
|
|
video_pipeline: VideoPipeline,
|
|
audio_streams: Vec<u32>,
|
|
duration_seconds: Option<f64>,
|
|
) -> 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<String> {
|
|
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",
|
|
]
|
|
}));
|
|
}
|
|
}
|