fix v_in in custom filter, add audio only mode

This commit is contained in:
jb-alvarado 2023-02-02 12:14:57 +01:00
parent f3cd45af3c
commit 537f664c06
5 changed files with 93 additions and 58 deletions

View File

@ -57,6 +57,7 @@ processing:
With 'custom_filter' it is possible, to apply further filters. The filter outputs With 'custom_filter' it is possible, to apply further filters. The filter outputs
should end with [c_v_out] for video filter, and [c_a_out] for audio filter. should end with [c_v_out] for video filter, and [c_a_out] for audio filter.
mode: playlist mode: playlist
audio_only: false
width: 1024 width: 1024
height: 576 height: 576
aspect: 1.778 aspect: 1.778

View File

@ -23,7 +23,7 @@ pub fn output(config: &PlayoutConfig, log_format: &str) -> process::Child {
"ffplayout" "ffplayout"
]; ];
if config.text.add_text && !config.text.text_from_filename { if config.text.add_text && !config.text.text_from_filename && !config.processing.audio_only {
if let Some(socket) = config.text.zmq_stream_socket.clone() { if let Some(socket) = config.text.zmq_stream_socket.clone() {
debug!( debug!(
"Using drawtext filter, listening on address: <yellow>{}</>", "Using drawtext filter, listening on address: <yellow>{}</>",

View File

@ -35,5 +35,9 @@ pub fn filter_node(filter: &str) -> (String, String) {
error!("Custom filter is not well formatted, use correct out link names (\"[c_v_out]\" and/or \"[c_a_out]\"). Filter skipped!") error!("Custom filter is not well formatted, use correct out link names (\"[c_v_out]\" and/or \"[c_a_out]\"). Filter skipped!")
} }
if filter.starts_with("[v_in]") {
video_filter = format!("[v_in]{video_filter}");
}
(video_filter, audio_filter) (video_filter, audio_filter)
} }

View File

@ -138,7 +138,10 @@ impl Filters {
let mut cmd = vec![]; let mut cmd = vec![];
if !a_chain.is_empty() { if !a_chain.is_empty() {
f_chain.push(';'); if !f_chain.is_empty() {
f_chain.push(';');
}
f_chain.push_str(&a_chain); f_chain.push_str(&a_chain);
} }
@ -153,7 +156,7 @@ impl Filters {
pub fn map(&mut self) -> Vec<String> { pub fn map(&mut self) -> Vec<String> {
let mut o_map = self.output_map.clone(); let mut o_map = self.output_map.clone();
if self.video_last == -1 { if self.video_last == -1 && !self.video_chain.is_empty() {
let v_map = "0:v".to_string(); let v_map = "0:v".to_string();
if !o_map.contains(&v_map) { if !o_map.contains(&v_map) {
@ -412,9 +415,19 @@ fn aspect_calc(aspect_string: &Option<String>, config: &PlayoutConfig) -> f64 {
} }
/// This realtime filter is important for HLS output to stay in sync. /// This realtime filter is important for HLS output to stay in sync.
fn realtime(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) { fn realtime(
node: &mut Media,
chain: &mut Filters,
config: &PlayoutConfig,
filter_type: FilterType,
) {
if config.general.generate.is_none() && config.out.mode == HLS { if config.general.generate.is_none() && config.out.mode == HLS {
let mut speed_filter = "realtime=speed=1".to_string(); let prefix = match filter_type {
Audio => "a",
Video => "",
};
let mut speed_filter = format!("{prefix}realtime=speed=1");
if let Some(begin) = &node.begin { if let Some(begin) = &node.begin {
let (delta, _) = get_delta(config, begin); let (delta, _) = get_delta(config, begin);
@ -424,12 +437,12 @@ fn realtime(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) {
let speed = duration / (duration + delta); let speed = duration / (duration + delta);
if speed > 0.0 && speed < 1.1 && delta < config.general.stop_threshold { if speed > 0.0 && speed < 1.1 && delta < config.general.stop_threshold {
speed_filter = format!("realtime=speed={speed}"); speed_filter = format!("{prefix}realtime=speed={speed}");
} }
} }
} }
chain.add_filter(&speed_filter, 0, Video); chain.add_filter(&speed_filter, 0, filter_type);
} }
} }
@ -504,54 +517,62 @@ pub fn filter_chains(
let mut filters = Filters::new(config.processing.audio_tracks, 0); let mut filters = Filters::new(config.processing.audio_tracks, 0);
if node.unit == Encoder { if node.unit == Encoder {
add_text(node, &mut filters, config, filter_chain); if !config.processing.audio_only {
add_text(node, &mut filters, config, filter_chain);
}
if let Some(f) = config.out.output_filter.clone() { if let Some(f) = config.out.output_filter.clone() {
process_output_filters(config, &mut filters, &f) process_output_filters(config, &mut filters, &f)
} else if config.out.output_count > 1 { } else if config.out.output_count > 1 && !config.processing.audio_only {
split_filter(&mut filters, config.out.output_count, 0, Video); split_filter(&mut filters, config.out.output_count, 0, Video);
} }
return filters; return filters;
} }
if let Some(probe) = node.probe.as_ref() { if !config.processing.audio_only {
if Path::new(&node.audio).is_file() { if let Some(probe) = node.probe.as_ref() {
filters.audio_position = 1; if Path::new(&node.audio).is_file() {
filters.audio_position = 1;
}
if let Some(v_stream) = &probe.video_streams.get(0) {
let aspect = aspect_calc(&v_stream.display_aspect_ratio, config);
let frame_per_sec = fps_calc(&v_stream.r_frame_rate, 1.0);
deinterlace(&v_stream.field_order, &mut filters);
pad(aspect, &mut filters, v_stream, config);
fps(frame_per_sec, &mut filters, config);
scale(
v_stream.width,
v_stream.height,
aspect,
&mut filters,
config,
);
}
extend_video(node, &mut filters);
} else {
fps(0.0, &mut filters, config);
scale(None, None, 1.0, &mut filters, config);
} }
if let Some(v_stream) = &probe.video_streams.get(0) { add_text(node, &mut filters, config, filter_chain);
let aspect = aspect_calc(&v_stream.display_aspect_ratio, config); fade(node, &mut filters, 0, Video);
let frame_per_sec = fps_calc(&v_stream.r_frame_rate, 1.0); overlay(node, &mut filters, config);
realtime(node, &mut filters, config, Video);
deinterlace(&v_stream.field_order, &mut filters);
pad(aspect, &mut filters, v_stream, config);
fps(frame_per_sec, &mut filters, config);
scale(
v_stream.width,
v_stream.height,
aspect,
&mut filters,
config,
);
}
extend_video(node, &mut filters);
} else {
fps(0.0, &mut filters, config);
scale(None, None, 1.0, &mut filters, config);
} }
add_text(node, &mut filters, config, filter_chain);
fade(node, &mut filters, 0, Video);
overlay(node, &mut filters, config);
realtime(node, &mut filters, config);
let (proc_vf, proc_af) = custom::filter_node(&config.processing.custom_filter); let (proc_vf, proc_af) = custom::filter_node(&config.processing.custom_filter);
let (list_vf, list_af) = custom::filter_node(&node.custom_filter); let (list_vf, list_af) = custom::filter_node(&node.custom_filter);
custom(&proc_vf, &mut filters, 0, Video); if config.processing.audio_only {
custom(&list_vf, &mut filters, 0, Video); realtime(node, &mut filters, config, Audio);
} else {
custom(&proc_vf, &mut filters, 0, Video);
custom(&list_vf, &mut filters, 0, Video);
}
for i in 0..config.processing.audio_tracks { for i in 0..config.processing.audio_tracks {
if node if node

View File

@ -19,7 +19,7 @@ pub const IMAGE_FORMAT: [&str; 21] = [
]; ];
// Some well known errors can be safely ignore // Some well known errors can be safely ignore
pub const FFMPEG_IGNORE_ERRORS: [&str; 10] = [ pub const FFMPEG_IGNORE_ERRORS: [&str; 11] = [
"ac-tex damaged", "ac-tex damaged",
"codec s302m, is muxed as a private data stream", "codec s302m, is muxed as a private data stream",
"corrupt decoded frame in stream", "corrupt decoded frame in stream",
@ -30,6 +30,7 @@ pub const FFMPEG_IGNORE_ERRORS: [&str; 10] = [
"skipped MB in I-frame at", "skipped MB in I-frame at",
"Thread message queue blocking", "Thread message queue blocking",
"Warning MVs not available", "Warning MVs not available",
"frame size not set",
]; ];
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
@ -156,6 +157,8 @@ pub struct Logging {
pub struct Processing { pub struct Processing {
pub help_text: String, pub help_text: String,
pub mode: ProcessMode, pub mode: ProcessMode,
#[serde(default)]
pub audio_only: bool,
pub width: i64, pub width: i64,
pub height: i64, pub height: i64,
pub aspect: f64, pub aspect: f64,
@ -328,24 +331,30 @@ impl PlayoutConfig {
(config.processing.width * config.processing.height / 16) / 2 (config.processing.width * config.processing.height / 16) / 2
); );
let mut process_cmd = vec_strings![ let mut process_cmd = vec_strings![];
"-pix_fmt",
"yuv420p", if config.processing.audio_only {
"-r", process_cmd.append(&mut vec_strings!["-vn"]);
&config.processing.fps, } else {
"-c:v", process_cmd.append(&mut vec_strings![
"mpeg2video", "-pix_fmt",
"-g", "yuv420p",
"1", "-r",
"-b:v", &config.processing.fps,
&bitrate, "-c:v",
"-minrate", "mpeg2video",
&bitrate, "-g",
"-maxrate", "1",
&bitrate, "-b:v",
"-bufsize", &bitrate,
&buff_size "-minrate",
]; &bitrate,
"-maxrate",
&bitrate,
"-bufsize",
&buff_size
]);
}
process_cmd.append(&mut pre_audio_codec( process_cmd.append(&mut pre_audio_codec(
config.processing.add_loudnorm, config.processing.add_loudnorm,