replace realtime filter with readrate parameter for hls mode
This commit is contained in:
parent
af8c08c319
commit
4b18d414b7
@ -6,6 +6,5 @@ ffplayout supports a stream copy mode since v0.20.0. A separate copy mode for vi
|
|||||||
- All files must use the same codecs and settings.
|
- All files must use the same codecs and settings.
|
||||||
- The video and audio lines of a file must be the same length.
|
- The video and audio lines of a file must be the same length.
|
||||||
- The codecs and A/V settings must be supported by mpegts and the output destination.
|
- The codecs and A/V settings must be supported by mpegts and the output destination.
|
||||||
- If the output mode is HLS, the time delta will increase over time, so the error threshold should be high enough to catch this.
|
|
||||||
|
|
||||||
**This mode is experimental and will not have the same stability as the stream mode.**
|
**This mode is experimental and will not have the same stability as the stream mode.**
|
||||||
|
@ -31,7 +31,7 @@ use crate::input::source_generator;
|
|||||||
use crate::utils::{log_line, prepare_output_cmd, valid_stream};
|
use crate::utils::{log_line, prepare_output_cmd, valid_stream};
|
||||||
use ffplayout_lib::{
|
use ffplayout_lib::{
|
||||||
utils::{
|
utils::{
|
||||||
controller::ProcessUnit::*, sec_to_time, stderr_reader, test_tcp_port, Media,
|
controller::ProcessUnit::*, get_delta, sec_to_time, stderr_reader, test_tcp_port, Media,
|
||||||
PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl,
|
PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl,
|
||||||
},
|
},
|
||||||
vec_strings,
|
vec_strings,
|
||||||
@ -178,11 +178,24 @@ pub fn write_hls(
|
|||||||
|
|
||||||
let mut enc_prefix = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format];
|
let mut enc_prefix = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format];
|
||||||
|
|
||||||
if config.processing.copy_video
|
let mut read_rate = 1.0;
|
||||||
|| (!config.processing.audio_only && config.processing.copy_audio)
|
|
||||||
{
|
if let Some(begin) = &node.begin {
|
||||||
enc_prefix.push("-re".to_string());
|
let (delta, _) = get_delta(config, begin);
|
||||||
|
let duration = node.out - node.seek;
|
||||||
|
let speed = duration / (duration + delta);
|
||||||
|
|
||||||
|
if node.seek == 0.0
|
||||||
|
&& speed > 0.0
|
||||||
|
&& speed < 1.3
|
||||||
|
&& delta < config.general.stop_threshold
|
||||||
|
{
|
||||||
|
read_rate = speed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enc_prefix.append(&mut vec_strings!["-readrate", read_rate]);
|
||||||
|
|
||||||
enc_prefix.append(&mut cmd);
|
enc_prefix.append(&mut cmd);
|
||||||
let enc_cmd = prepare_output_cmd(config, enc_prefix, &node.filter);
|
let enc_cmd = prepare_output_cmd(config, enc_prefix, &node.filter);
|
||||||
|
|
||||||
|
@ -11,8 +11,7 @@ mod custom;
|
|||||||
pub mod v_drawtext;
|
pub mod v_drawtext;
|
||||||
|
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
controller::ProcessUnit::*, fps_calc, get_delta, is_close, Media, MediaProbe, OutputMode::*,
|
controller::ProcessUnit::*, fps_calc, is_close, Media, MediaProbe, OutputMode::*, PlayoutConfig,
|
||||||
PlayoutConfig,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::vec_strings;
|
use super::vec_strings;
|
||||||
@ -402,38 +401,6 @@ fn aspect_calc(aspect_string: &Option<String>, config: &PlayoutConfig) -> f64 {
|
|||||||
source_aspect
|
source_aspect
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This realtime filter is important for HLS output to stay in sync.
|
|
||||||
fn realtime(
|
|
||||||
node: &mut Media,
|
|
||||||
chain: &mut Filters,
|
|
||||||
config: &PlayoutConfig,
|
|
||||||
filter_type: FilterType,
|
|
||||||
) {
|
|
||||||
if config.general.generate.is_none() && config.out.mode == HLS {
|
|
||||||
let prefix = match filter_type {
|
|
||||||
Audio => "a",
|
|
||||||
Video => "",
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut speed_filter = format!("{prefix}realtime=speed=1");
|
|
||||||
|
|
||||||
if let Some(begin) = &node.begin {
|
|
||||||
let (delta, _) = get_delta(config, begin);
|
|
||||||
|
|
||||||
if delta < 0.0 && node.seek == 0.0 {
|
|
||||||
let duration = node.out - node.seek;
|
|
||||||
let speed = duration / (duration + delta);
|
|
||||||
|
|
||||||
if speed > 0.0 && speed < 1.1 && delta < config.general.stop_threshold {
|
|
||||||
speed_filter = format!("{prefix}realtime=speed={speed}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chain.add_filter(&speed_filter, 0, filter_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn split_filter(chain: &mut Filters, count: usize, nr: i32, filter_type: FilterType) {
|
pub fn split_filter(chain: &mut Filters, count: usize, nr: i32, filter_type: FilterType) {
|
||||||
if count > 1 {
|
if count > 1 {
|
||||||
let out_link = match filter_type {
|
let out_link = match filter_type {
|
||||||
@ -549,7 +516,6 @@ pub fn filter_chains(
|
|||||||
add_text(node, &mut filters, config, filter_chain);
|
add_text(node, &mut filters, config, filter_chain);
|
||||||
fade(node, &mut filters, 0, Video);
|
fade(node, &mut filters, 0, Video);
|
||||||
overlay(node, &mut filters, config);
|
overlay(node, &mut filters, config);
|
||||||
realtime(node, &mut filters, config, Video);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (proc_vf, proc_af) = if node.unit == Ingest {
|
let (proc_vf, proc_af) = if node.unit == Ingest {
|
||||||
@ -560,9 +526,7 @@ pub fn filter_chains(
|
|||||||
|
|
||||||
let (list_vf, list_af) = custom::filter_node(&node.custom_filter);
|
let (list_vf, list_af) = custom::filter_node(&node.custom_filter);
|
||||||
|
|
||||||
if config.processing.audio_only && !config.processing.copy_audio {
|
if !config.processing.copy_video {
|
||||||
realtime(node, &mut filters, config, Audio);
|
|
||||||
} else if !config.processing.copy_video {
|
|
||||||
custom(&proc_vf, &mut filters, 0, Video);
|
custom(&proc_vf, &mut filters, 0, Video);
|
||||||
custom(&list_vf, &mut filters, 0, Video);
|
custom(&list_vf, &mut filters, 0, Video);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user