From 94e02ac3678c0f8cdec97002f30e08beb45e748b Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Thu, 30 Nov 2023 09:04:21 +0100 Subject: [PATCH] loop separate audio when is to short --- ffplayout-engine/src/input/playlist.rs | 4 +- ffplayout-engine/src/rpc/server.rs | 4 +- lib/src/filter/mod.rs | 45 ++++++++++++---------- lib/src/utils/folder.rs | 8 ++-- lib/src/utils/json_serializer.rs | 2 + lib/src/utils/json_validate.rs | 2 +- lib/src/utils/mod.rs | 53 ++++++++++++++++++-------- 7 files changed, 72 insertions(+), 46 deletions(-) diff --git a/ffplayout-engine/src/input/playlist.rs b/ffplayout-engine/src/input/playlist.rs index d8becd28..49aed131 100644 --- a/ffplayout-engine/src/input/playlist.rs +++ b/ffplayout-engine/src/input/playlist.rs @@ -580,7 +580,7 @@ pub fn gen_source( trace!("Clip out: {duration}, duration: {}", node.duration); if valid_source(&node.source) { - node.add_probe(); + node.add_probe(true); if node .source @@ -616,7 +616,7 @@ pub fn gen_source( } if filler_media.probe.is_none() { - filler_media.add_probe(); + filler_media.add_probe(false); } if node.duration > duration && filler_media.duration > duration { diff --git a/ffplayout-engine/src/rpc/server.rs b/ffplayout-engine/src/rpc/server.rs index ec29627b..f98a7963 100644 --- a/ffplayout-engine/src/rpc/server.rs +++ b/ffplayout-engine/src/rpc/server.rs @@ -212,7 +212,7 @@ fn control_back( let mut data_map = Map::new(); let mut media = current_list[index - 2].clone(); play_control.current_index.fetch_sub(2, Ordering::SeqCst); - media.add_probe(); + media.add_probe(false); let (delta, _) = get_delta(config, &media.begin.unwrap_or(0.0)); *time_shift = delta; @@ -258,7 +258,7 @@ fn control_next( let mut data_map = Map::new(); let mut media = current_list[index].clone(); - media.add_probe(); + media.add_probe(false); let (delta, _) = get_delta(config, &media.begin.unwrap_or(0.0)); *time_shift = delta; diff --git a/lib/src/filter/mod.rs b/lib/src/filter/mod.rs index f4e040ff..7c5db609 100644 --- a/lib/src/filter/mod.rs +++ b/lib/src/filter/mod.rs @@ -11,7 +11,7 @@ mod custom; pub mod v_drawtext; use crate::utils::{ - controller::ProcessUnit::*, fps_calc, is_close, Media, MediaProbe, OutputMode::*, PlayoutConfig, + controller::ProcessUnit::*, fps_calc, is_close, Media, OutputMode::*, PlayoutConfig, }; use super::vec_strings; @@ -265,16 +265,21 @@ fn scale( fn fade(node: &mut Media, chain: &mut Filters, nr: i32, filter_type: FilterType) { let mut t = ""; + let mut fade_audio = false; if filter_type == Audio { - t = "a" + t = "a"; + + if node.duration_audio > 0.0 && node.duration_audio != node.duration { + fade_audio = true; + } } if node.seek > 0.0 || node.unit == Ingest { chain.add_filter(&format!("{t}fade=in:st=0:d=0.5"), nr, filter_type) } - if node.out != node.duration && node.out - node.seek > 1.0 { + if (node.out != node.duration && node.out - node.seek > 1.0) || fade_audio { chain.add_filter( &format!("{t}fade=out:st={}:d=1.0", (node.out - node.seek - 1.0)), nr, @@ -360,24 +365,22 @@ fn add_audio(node: &Media, chain: &mut Filters, nr: i32) { } fn extend_audio(node: &mut Media, chain: &mut Filters, nr: i32) { - let probe = if Path::new(&node.audio).is_file() { - Some(MediaProbe::new(&node.audio)) - } else { - node.probe.clone() - }; - - if let Some(audio_duration) = probe - .as_ref() - .and_then(|p| p.audio_streams.get(0)) - .and_then(|a| a.duration.clone()) - .and_then(|a| a.parse::().ok()) - { - if node.out - node.seek > audio_duration - node.seek + 0.1 && node.duration >= node.out { - chain.add_filter( - &format!("apad=whole_dur={}", node.out - node.seek), - nr, - Audio, - ) + if !Path::new(&node.audio).is_file() { + if let Some(audio_duration) = node + .probe + .as_ref() + .and_then(|p| p.audio_streams.get(0)) + .and_then(|a| a.duration.clone()) + .and_then(|a| a.parse::().ok()) + { + if node.out - node.seek > audio_duration - node.seek + 0.1 && node.duration >= node.out + { + chain.add_filter( + &format!("apad=whole_dur={}", node.out - node.seek), + nr, + Audio, + ) + } } } } diff --git a/lib/src/utils/folder.rs b/lib/src/utils/folder.rs index 74cd251e..cf521719 100644 --- a/lib/src/utils/folder.rs +++ b/lib/src/utils/folder.rs @@ -136,7 +136,7 @@ impl Iterator for FolderSource { { let i = self.player_control.current_index.load(Ordering::SeqCst); self.current_node = self.player_control.current_list.lock().unwrap()[i].clone(); - self.current_node.add_probe(); + self.current_node.add_probe(false); self.current_node .add_filter(&self.config, &self.filter_chain); self.current_node.begin = Some(get_sec()); @@ -162,7 +162,7 @@ impl Iterator for FolderSource { } self.current_node = self.player_control.current_list.lock().unwrap()[0].clone(); - self.current_node.add_probe(); + self.current_node.add_probe(false); self.current_node .add_filter(&self.config, &self.filter_chain); self.current_node.begin = Some(get_sec()); @@ -192,7 +192,7 @@ pub fn fill_filler_list( let mut media = Media::new(index, &entry.path().to_string_lossy(), false); if player_control.is_none() { - media.add_probe(); + media.add_probe(false); } filler_list.push(media); @@ -217,7 +217,7 @@ pub fn fill_filler_list( let mut media = Media::new(0, &config.storage.filler.to_string_lossy(), false); if player_control.is_none() { - media.add_probe(); + media.add_probe(false); } filler_list.push(media); diff --git a/lib/src/utils/json_serializer.rs b/lib/src/utils/json_serializer.rs index 9aac1425..0212aaca 100644 --- a/lib/src/utils/json_serializer.rs +++ b/lib/src/utils/json_serializer.rs @@ -106,11 +106,13 @@ fn loop_playlist( seek: item.seek, out: item.out, duration: item.duration, + duration_audio: item.duration_audio, category: item.category.clone(), source: item.source.clone(), audio: item.audio.clone(), cmd: item.cmd.clone(), probe: item.probe.clone(), + probe_audio: item.probe_audio.clone(), process: Some(true), unit: Decoder, last_ad: Some(false), diff --git a/lib/src/utils/json_validate.rs b/lib/src/utils/json_validate.rs index a2889066..000cce71 100644 --- a/lib/src/utils/json_validate.rs +++ b/lib/src/utils/json_validate.rs @@ -44,7 +44,7 @@ fn check_media( enc_cmd.append(&mut vec_strings!["-ss", seek]); } - node.add_probe(); + node.add_probe(false); if node.probe.clone().and_then(|p| p.format).is_none() { return Err(ProcError::Custom(format!( diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index 9c933ad2..da5997b6 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -68,6 +68,9 @@ pub struct Media { pub out: f64, pub duration: f64, + #[serde(skip_serializing, skip_deserializing)] + pub duration_audio: f64, + #[serde( default, deserialize_with = "null_string", @@ -96,6 +99,9 @@ pub struct Media { #[serde(skip_serializing, skip_deserializing)] pub probe: Option, + #[serde(skip_serializing, skip_deserializing)] + pub probe_audio: Option, + #[serde(skip_serializing, skip_deserializing)] pub last_ad: Option, @@ -132,6 +138,7 @@ impl Media { seek: 0.0, out: duration, duration, + duration_audio: 0.0, category: String::new(), source: src.to_string(), audio: String::new(), @@ -139,6 +146,7 @@ impl Media { filter: None, custom_filter: String::new(), probe, + probe_audio: None, last_ad: Some(false), next_ad: Some(false), process: Some(true), @@ -146,7 +154,7 @@ impl Media { } } - pub fn add_probe(&mut self) { + pub fn add_probe(&mut self, check_audio: bool) { if self.probe.is_none() { let probe = MediaProbe::new(&self.source); self.probe = Some(probe.clone()); @@ -163,6 +171,19 @@ impl Media { self.out = dur; } } + + if check_audio && Path::new(&self.audio).is_file() { + let probe_audio = MediaProbe::new(&self.audio); + self.probe_audio = Some(probe_audio.clone()); + + if !probe_audio.audio_streams.is_empty() { + self.duration_audio = probe_audio.audio_streams[0] + .duration + .clone() + .and_then(|d| d.parse::().ok()) + .unwrap_or_default() + } + } } } @@ -498,6 +519,7 @@ pub fn loop_filler(node: &Media) -> Vec { pub fn seek_and_length(node: &Media) -> Vec { let mut source_cmd = vec![]; let mut cut_audio = false; + let mut loop_audio = false; if node.seek > 0.5 { source_cmd.append(&mut vec_strings!["-ss", node.seek]) @@ -505,30 +527,29 @@ pub fn seek_and_length(node: &Media) -> Vec { source_cmd.append(&mut vec_strings!["-i", node.source.clone()]); - if Path::new(&node.audio).is_file() { - let audio_probe = MediaProbe::new(&node.audio); + if node.duration > node.out { + source_cmd.append(&mut vec_strings!["-t", node.out - node.seek]); + } + if !node.audio.is_empty() { if node.seek > 0.5 { - source_cmd.append(&mut vec_strings!["-ss", node.seek]) + source_cmd.append(&mut vec_strings!["-ss", node.seek]); + } + + if node.duration_audio > node.duration { + cut_audio = true; + } else if node.duration_audio < node.duration { + source_cmd.append(&mut vec_strings!["-stream_loop", -1]); + loop_audio = true; } source_cmd.append(&mut vec_strings!["-i", node.audio.clone()]); - if !audio_probe.audio_streams.is_empty() - && audio_probe.audio_streams[0] - .duration - .clone() - .and_then(|d| d.parse::().ok()) - > Some(node.out - node.seek) - { - cut_audio = true; + if cut_audio || loop_audio { + source_cmd.append(&mut vec_strings!["-t", node.out - node.seek]); } } - if node.duration > node.out || cut_audio { - source_cmd.append(&mut vec_strings!["-t", node.out - node.seek]); - } - source_cmd }