default when category is net set, use filler_clip from config instead of a dummy clip
This commit is contained in:
parent
b57f078f8a
commit
baf10cfdda
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1014,7 +1014,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout"
|
||||
version = "0.13.2"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"crossbeam-channel 0.5.6",
|
||||
@ -1062,7 +1062,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-lib"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel 0.5.6",
|
||||
|
@ -4,7 +4,7 @@ description = "24/7 playout based on rust and ffmpeg"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.13.2"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
@ -479,8 +479,13 @@ fn gen_source(
|
||||
error!("Source not found: <b><magenta>{}</></b>", node.source);
|
||||
}
|
||||
let (source, cmd) = gen_dummy(config, node.out - node.seek);
|
||||
node.source = source;
|
||||
node.source = source.clone();
|
||||
node.cmd = Some(cmd);
|
||||
|
||||
if source == config.storage.filler_clip {
|
||||
node.add_probe();
|
||||
}
|
||||
|
||||
node.add_filter(config, filter_chain);
|
||||
}
|
||||
|
||||
|
@ -119,11 +119,11 @@ pub fn player(
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(proc) => proc,
|
||||
Err(e) => {
|
||||
error!("couldn't spawn decoder process: {}", e);
|
||||
panic!("couldn't spawn decoder process: {}", e)
|
||||
}
|
||||
Ok(proc) => proc,
|
||||
};
|
||||
|
||||
let mut dec_reader = BufReader::new(dec_proc.stdout.take().unwrap());
|
||||
|
@ -4,7 +4,7 @@ description = "Library for ffplayout"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
@ -167,19 +167,18 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &PlayoutConfig) {
|
||||
}
|
||||
|
||||
fn extend_video(node: &mut Media, chain: &mut Filters) {
|
||||
if let Some(duration) = node
|
||||
if let Some(video_duration) = node
|
||||
.probe
|
||||
.as_ref()
|
||||
.and_then(|p| p.video_streams.as_ref())
|
||||
.and_then(|v| v[0].duration.as_ref())
|
||||
.and_then(|v| v.parse::<f64>().ok())
|
||||
{
|
||||
let duration_float = duration.clone().parse::<f64>().unwrap();
|
||||
|
||||
if node.out - node.seek > duration_float - node.seek + 0.1 {
|
||||
if node.out - node.seek > video_duration - node.seek + 0.1 && node.duration >= node.out {
|
||||
chain.add_filter(
|
||||
&format!(
|
||||
"tpad=stop_mode=add:stop_duration={}",
|
||||
(node.out - node.seek) - (duration_float - node.seek)
|
||||
(node.out - node.seek) - (video_duration - node.seek)
|
||||
),
|
||||
"video",
|
||||
)
|
||||
@ -221,15 +220,14 @@ fn add_audio(node: &mut Media, chain: &mut Filters) {
|
||||
}
|
||||
|
||||
fn extend_audio(node: &mut Media, chain: &mut Filters) {
|
||||
if let Some(duration) = node
|
||||
if let Some(audio_duration) = node
|
||||
.probe
|
||||
.as_ref()
|
||||
.and_then(|p| p.audio_streams.as_ref())
|
||||
.and_then(|a| a[0].duration.as_ref())
|
||||
.and_then(|a| a.parse::<f64>().ok())
|
||||
{
|
||||
let duration_float = duration.clone().parse::<f64>().unwrap();
|
||||
|
||||
if node.out - node.seek > duration_float - node.seek + 0.1 {
|
||||
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), "audio")
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ pub struct Media {
|
||||
pub out: f64,
|
||||
pub duration: f64,
|
||||
|
||||
#[serde(deserialize_with = "null_string")]
|
||||
#[serde(default, deserialize_with = "null_string")]
|
||||
pub category: String,
|
||||
#[serde(deserialize_with = "null_string")]
|
||||
pub source: String,
|
||||
@ -394,8 +394,40 @@ pub fn check_sync(config: &PlayoutConfig, delta: f64) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Loop source until target duration is reached.
|
||||
fn loop_input(source: &str, source_duration: f64, target_duration: f64) -> Vec<String> {
|
||||
let loop_count = (target_duration / source_duration).ceil() as i32;
|
||||
|
||||
info!("Loop <b><magenta>{source}</></b> <yellow>{loop_count}</> times, total duration: {target_duration:.2}");
|
||||
|
||||
vec_strings![
|
||||
"-stream_loop",
|
||||
loop_count.to_string(),
|
||||
"-i",
|
||||
source,
|
||||
"-t",
|
||||
target_duration.to_string()
|
||||
]
|
||||
}
|
||||
|
||||
/// Create a dummy clip as a placeholder for missing video files.
|
||||
pub fn gen_dummy(config: &PlayoutConfig, duration: f64) -> (String, Vec<String>) {
|
||||
// create placeholder from config filler.
|
||||
if Path::new(&config.storage.filler_clip).is_file() {
|
||||
let probe = MediaProbe::new(&config.storage.filler_clip);
|
||||
|
||||
if let Some(length) = probe
|
||||
.format
|
||||
.and_then(|f| f.duration)
|
||||
.and_then(|d| d.parse::<f64>().ok())
|
||||
{
|
||||
let cmd = loop_input(&config.storage.filler_clip, length, duration);
|
||||
|
||||
return (config.storage.filler_clip.clone(), cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// create colored placeholder.
|
||||
let color = "#121212";
|
||||
let source = format!(
|
||||
"color=c={color}:s={}x{}:d={duration}",
|
||||
@ -551,6 +583,11 @@ pub fn stderr_reader(buffer: BufReader<ChildStderr>, suffix: &str) -> Result<(),
|
||||
"<bright black>[{suffix}]</> {}",
|
||||
format_log_line(line, "error")
|
||||
)
|
||||
} else if line.contains("[fatal]") {
|
||||
error!(
|
||||
"<bright black>[{suffix}]</> {}",
|
||||
format_log_line(line, "fatal")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user