diff --git a/ffplayout-engine/src/rpc/mod.rs b/ffplayout-engine/src/rpc/mod.rs index cf2653b4..07891052 100644 --- a/ffplayout-engine/src/rpc/mod.rs +++ b/ffplayout-engine/src/rpc/mod.rs @@ -85,7 +85,7 @@ pub fn json_rpc_server( { let filter = get_filter_from_json(map["message"].to_string()); - // TODO: in Rust 1.64 use let_chains instead + // TODO: in Rust 1.65 use let_chains instead if !filter.is_empty() && config.text.zmq_stream_socket.is_some() { let mut clips_filter = playout_stat.chain.lock().unwrap(); *clips_filter = vec![filter.clone()]; diff --git a/lib/src/filter/mod.rs b/lib/src/filter/mod.rs index c5d22692..8725383b 100644 --- a/lib/src/filter/mod.rs +++ b/lib/src/filter/mod.rs @@ -171,7 +171,7 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { && Path::new(&config.processing.logo).is_file() && &node.category != "advertisement" { - let mut logo_chain = v_overlay::filter_node(config, false); + let mut logo_chain = v_overlay::filter_node(config); if node.last_ad.unwrap_or(false) { logo_chain.push_str(",fade=in:st=0:d=1.0:alpha=1") @@ -183,9 +183,6 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { ) } - logo_chain - .push_str(format!("[l];[v][l]{}:shortest=1", config.processing.logo_filter).as_str()); - chain.add_filter(&logo_chain, Video); } } diff --git a/lib/src/filter/v_drawtext.rs b/lib/src/filter/v_drawtext.rs index e93bd7ed..58bb0fe2 100644 --- a/lib/src/filter/v_drawtext.rs +++ b/lib/src/filter/v_drawtext.rs @@ -26,7 +26,7 @@ pub fn filter_node( None => config.text.zmq_stream_socket.clone(), }; - // TODO: in Rust 1.64 use let_chains instead + // TODO: in Rust 1.65 use let_chains instead if config.text.text_from_filename && node.is_some() { let source = node .unwrap_or(&Media::new(0, String::new(), false)) diff --git a/lib/src/filter/v_overlay.rs b/lib/src/filter/v_overlay.rs index ff122310..f32cf9a7 100644 --- a/lib/src/filter/v_overlay.rs +++ b/lib/src/filter/v_overlay.rs @@ -3,30 +3,24 @@ use crate::utils::PlayoutConfig; /// Overlay Filter /// /// When a logo is set, we create here the filter for the server. -pub fn filter_node(config: &PlayoutConfig, add_tail: bool) -> String { - let mut logo_chain = String::new(); +pub fn filter_node(config: &PlayoutConfig) -> String { + let mut fps = config.processing.fps; + let mut fps_filter = String::new(); if !config.processing.add_logo { - return logo_chain; + return String::new(); } - if let Some(fps) = config.processing.logo_fps { - let opacity = format!( - "format=rgba,colorchannelmixer=aa={}", - config.processing.logo_opacity - ); - let pts = format!("setpts=N/({fps}*TB)"); - logo_chain = format!( - "null[v];movie={}:loop=0,{pts},{opacity}", - config.processing.logo - ); - - if add_tail { - logo_chain.push_str( - format!("[l];[v][l]{}:shortest=1", config.processing.logo_filter).as_str(), - ); - } + if let Some(f) = config.processing.logo_fps { + fps = f; }; - logo_chain + if config.processing.fps != fps { + fps_filter = format!(",fps={}", config.processing.fps); + } + + format!( + "null[v];movie={}:loop=0,setpts=N/({fps}*TB),format=rgba,colorchannelmixer=aa={}{fps_filter}[l];[v][l]{}:shortest=1", + config.processing.logo, config.processing.logo_opacity, config.processing.logo_filter + ) } diff --git a/lib/src/utils/config.rs b/lib/src/utils/config.rs index be81ee3b..740f337c 100644 --- a/lib/src/utils/config.rs +++ b/lib/src/utils/config.rs @@ -17,6 +17,13 @@ pub const IMAGE_FORMAT: [&str; 21] = [ "png", "psd", "ppm", "sgi", "svg", "tga", "tif", "webp", ]; +// Some well known errors can be safely ignore +pub const FFMPEG_IGNORE_ERRORS: [&str; 3] = [ + "Referenced QT chapter track not found", + "ac-tex damaged", + "Warning MVs not available", +]; + /// Global Config /// /// This we init ones, when ffplayout is starting and use them globally in the hole program. diff --git a/lib/src/utils/controller.rs b/lib/src/utils/controller.rs index cede1644..2354c428 100644 --- a/lib/src/utils/controller.rs +++ b/lib/src/utils/controller.rs @@ -92,9 +92,7 @@ impl ProcessControl { } } - if let Err(e) = self.wait(unit) { - return Err(e); - }; + self.wait(unit)?; Ok(()) } diff --git a/lib/src/utils/mod.rs b/lib/src/utils/mod.rs index 3fb47760..f65c8e2e 100644 --- a/lib/src/utils/mod.rs +++ b/lib/src/utils/mod.rs @@ -34,7 +34,9 @@ mod logging; #[cfg(windows)] mod windows; -pub use config::{self as playout_config, PlayoutConfig, DUMMY_LEN, IMAGE_FORMAT}; +pub use config::{ + self as playout_config, PlayoutConfig, DUMMY_LEN, FFMPEG_IGNORE_ERRORS, IMAGE_FORMAT, +}; pub use controller::{PlayerControl, PlayoutStatus, ProcessControl, ProcessUnit::*}; pub use generator::generate_playlist; pub use json_serializer::{read_json, JsonPlaylist}; @@ -497,14 +499,6 @@ pub fn seek_and_length(node: &Media) -> Vec { source_cmd.append(&mut vec_strings!["-ss", node.seek]) } - if file_extension(Path::new(&node.source)) - .unwrap_or_default() - .to_lowercase() - == "mp4" - { - source_cmd.append(&mut vec_strings!["-ignore_chapters", "1"]); - } - source_cmd.append(&mut vec_strings!["-i", node.source.clone()]); if Path::new(&node.audio).is_file() { @@ -719,7 +713,9 @@ pub fn stderr_reader( "[{suffix}] {}", format_log_line(line, "warning") ) - } else if line.contains("[error]") || line.contains("[fatal]") { + } else if (line.contains("[error]") || line.contains("[fatal]")) + && !FFMPEG_IGNORE_ERRORS.iter().any(|i| line.contains(*i)) + { error!( "[{suffix}] {}", line.replace("[error]", "").replace("[fatal]", "")