WIP Playlist error handling. Filtering is broken.
This commit is contained in:
parent
bc69300a1c
commit
934fd289cb
@ -4,15 +4,15 @@ use std::path::Path;
|
||||
use crate::utils::{is_close, Config, Media};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
struct Filters {
|
||||
audio_chain: Option<String>,
|
||||
video_chain: Option<String>,
|
||||
audio_map: Option<String>,
|
||||
video_map: Option<String>,
|
||||
pub struct Filters {
|
||||
pub audio_chain: Option<String>,
|
||||
pub video_chain: Option<String>,
|
||||
pub audio_map: Option<String>,
|
||||
pub video_map: Option<String>,
|
||||
}
|
||||
|
||||
impl Filters {
|
||||
fn new() -> Self {
|
||||
pub fn new() -> Self {
|
||||
Filters {
|
||||
audio_chain: None,
|
||||
video_chain: None,
|
||||
@ -58,13 +58,26 @@ impl Filters {
|
||||
}
|
||||
}
|
||||
|
||||
fn deinterlace(field_order: Option<String>, chain: &mut Filters) {
|
||||
if field_order.is_some() && field_order.unwrap() != "progressive".to_string() {
|
||||
fn deinterlace(node: Media, chain: &mut Filters) {
|
||||
// if node.probe.is_none() {
|
||||
// return;
|
||||
// }
|
||||
|
||||
let v_stream = &node.probe.unwrap().video_streams.unwrap()[0];
|
||||
|
||||
if v_stream.field_order.is_some() && v_stream.field_order.unwrap() != "progressive".to_string()
|
||||
{
|
||||
chain.add_filter("yadif=0:-1:0".into(), "video".into())
|
||||
}
|
||||
}
|
||||
|
||||
fn pad(aspect: f64, chain: &mut Filters, config: &Config) {
|
||||
fn pad(node: &Media, chain: &mut Filters, config: &Config) {
|
||||
if node.probe.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let aspect = aspect_calc(node);
|
||||
|
||||
if !is_close(aspect, config.processing.aspect, 0.03) {
|
||||
if aspect < config.processing.aspect {
|
||||
chain.add_filter(
|
||||
@ -88,7 +101,13 @@ fn pad(aspect: f64, chain: &mut Filters, config: &Config) {
|
||||
}
|
||||
}
|
||||
|
||||
fn fps(fps: f64, chain: &mut Filters, config: &Config) {
|
||||
fn fps(node: &Media, chain: &mut Filters, config: &Config) {
|
||||
if node.probe.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let fps = fps_calc(node);
|
||||
|
||||
if fps != config.processing.fps {
|
||||
chain.add_filter(
|
||||
format!("fps={}", config.processing.fps).into(),
|
||||
@ -97,7 +116,17 @@ fn fps(fps: f64, chain: &mut Filters, config: &Config) {
|
||||
}
|
||||
}
|
||||
|
||||
fn scale(width: i64, height: i64, aspect: f64, chain: &mut Filters, config: &Config) {
|
||||
fn scale(node: &Media, chain: &mut Filters, config: &Config) {
|
||||
if node.probe.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let v_stream = node.probe.unwrap().video_streams.unwrap()[0];
|
||||
let aspect = aspect_calc(node);
|
||||
|
||||
let width = v_stream.width.unwrap();
|
||||
let height = v_stream.height.unwrap();
|
||||
|
||||
if width != config.processing.width || height != config.processing.height {
|
||||
chain.add_filter(
|
||||
format!(
|
||||
@ -136,7 +165,7 @@ fn fade(node: &mut Media, chain: &mut Filters, codec_type: String) {
|
||||
}
|
||||
}
|
||||
|
||||
fn overlay(node: &mut Media, chain: &mut Filters, config: &Config) {
|
||||
pub fn overlay(node: &mut Media, chain: &mut Filters, config: &Config) {
|
||||
if config.processing.add_logo
|
||||
&& Path::new(&config.processing.logo).is_file()
|
||||
&& node.category != "advertisement".to_string()
|
||||
@ -146,7 +175,10 @@ fn overlay(node: &mut Media, chain: &mut Filters, config: &Config) {
|
||||
config.processing.logo_opacity
|
||||
);
|
||||
let logo_loop = "loop=loop=-1:size=1:start=0";
|
||||
let mut logo_chain = format!("null[v];movie={},{logo_loop},{opacity}", config.processing.logo);
|
||||
let mut logo_chain = format!(
|
||||
"null[v];movie={},{logo_loop},{opacity}",
|
||||
config.processing.logo
|
||||
);
|
||||
|
||||
if node.last_ad.unwrap() {
|
||||
logo_chain.push_str(",fade=in:st=0:d=1.0:alpha=1")
|
||||
@ -174,7 +206,13 @@ fn extend_video(node: &mut Media, chain: &mut Filters) {
|
||||
let duration_float = video_duration.clone().unwrap().parse::<f64>().unwrap();
|
||||
|
||||
if node.out - node.seek > duration_float - node.seek + 0.1 {
|
||||
chain.add_filter(format!("tpad=stop_mode=add:stop_duration={}", (node.out - node.seek) - (duration_float - node.seek)) , "video".into())
|
||||
chain.add_filter(
|
||||
format!(
|
||||
"tpad=stop_mode=add:stop_duration={}",
|
||||
(node.out - node.seek) - (duration_float - node.seek)
|
||||
),
|
||||
"video".into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,8 +238,11 @@ fn extend_audio(node: &mut Media, chain: &mut Filters) {
|
||||
if audio_duration.is_some() {
|
||||
let duration_float = audio_duration.clone().unwrap().parse::<f64>().unwrap();
|
||||
|
||||
if node.out - node.seek > duration_float- node.seek + 0.1 {
|
||||
chain.add_filter(format!("apad=whole_dur={}", node.out - node.seek), "audio".into())
|
||||
if node.out - node.seek > duration_float - node.seek + 0.1 {
|
||||
chain.add_filter(
|
||||
format!("apad=whole_dur={}", node.out - node.seek),
|
||||
"audio".into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,53 +250,49 @@ fn extend_audio(node: &mut Media, chain: &mut Filters) {
|
||||
|
||||
fn audio_volume(chain: &mut Filters, config: &Config) {
|
||||
if config.processing.volume != 1.0 {
|
||||
chain.add_filter(format!("volume={}", config.processing.volume), "audio".into())
|
||||
chain.add_filter(
|
||||
format!("volume={}", config.processing.volume),
|
||||
"audio".into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn aspect_calc(node: &Media) -> f64 {
|
||||
let v_stream = node.probe.unwrap().video_streams.unwrap()[0];
|
||||
let aspect_string = v_stream.display_aspect_ratio.clone().unwrap();
|
||||
let aspect_vec: Vec<&str> = aspect_string.split(':').collect();
|
||||
let w: f64 = aspect_vec[0].parse().unwrap();
|
||||
let h: f64 = aspect_vec[1].parse().unwrap();
|
||||
let source_aspect: f64 = w as f64 / h as f64;
|
||||
|
||||
source_aspect
|
||||
}
|
||||
|
||||
fn fps_calc(node: &Media) -> f64 {
|
||||
let v_stream = node.probe.unwrap().video_streams.unwrap()[0];
|
||||
let frame_rate_vec: Vec<&str> = v_stream.r_frame_rate.split('/').collect();
|
||||
let rate: f64 = frame_rate_vec[0].parse().unwrap();
|
||||
let factor: f64 = frame_rate_vec[1].parse().unwrap();
|
||||
let fps: f64 = rate / factor;
|
||||
|
||||
fps
|
||||
}
|
||||
|
||||
pub fn filter_chains(node: &mut Media, config: &Config) -> Vec<String> {
|
||||
let mut filters = Filters::new();
|
||||
let probe = node.probe.clone();
|
||||
|
||||
match probe {
|
||||
Some(p) => {
|
||||
// let a_stream = &p.audio_streams.unwrap()[0];
|
||||
if p.video_streams.is_some() {
|
||||
let v_stream = &p.video_streams.unwrap()[0];
|
||||
let aspect_string = v_stream.display_aspect_ratio.clone().unwrap();
|
||||
let aspect_vec: Vec<&str> = aspect_string.split(':').collect();
|
||||
let w: f64 = aspect_vec[0].parse().unwrap();
|
||||
let h: f64 = aspect_vec[1].parse().unwrap();
|
||||
let source_aspect: f64 = w as f64 / h as f64;
|
||||
let frame_rate_vec: Vec<&str> = v_stream.r_frame_rate.split('/').collect();
|
||||
let rate: f64 = frame_rate_vec[0].parse().unwrap();
|
||||
let factor: f64 = frame_rate_vec[1].parse().unwrap();
|
||||
let frames_per_second: f64 = rate / factor;
|
||||
deinterlace(node.clone(), &mut filters);
|
||||
pad(&node, &mut filters, &config);
|
||||
fps(&node, &mut filters, &config);
|
||||
scale(&node, &mut filters, &config);
|
||||
extend_video(node, &mut filters);
|
||||
fade(node, &mut filters, "video".into());
|
||||
overlay(node, &mut filters, &config);
|
||||
|
||||
deinterlace(v_stream.field_order.clone(), &mut filters);
|
||||
pad(source_aspect, &mut filters, &config);
|
||||
fps(frames_per_second, &mut filters, &config);
|
||||
scale(
|
||||
v_stream.width.unwrap(),
|
||||
v_stream.height.unwrap(),
|
||||
source_aspect,
|
||||
&mut filters,
|
||||
&config,
|
||||
);
|
||||
extend_video(node, &mut filters);
|
||||
fade(node, &mut filters, "video".into());
|
||||
overlay(node, &mut filters, &config);
|
||||
|
||||
add_audio(node, &mut filters);
|
||||
extend_audio(node, &mut filters);
|
||||
fade(node, &mut filters, "audio".into());
|
||||
audio_volume(&mut filters, &config);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
println!("Clip has no media probe object. No filter applied!")
|
||||
}
|
||||
}
|
||||
add_audio(node, &mut filters);
|
||||
extend_audio(node, &mut filters);
|
||||
fade(node, &mut filters, "audio".into());
|
||||
audio_volume(&mut filters, &config);
|
||||
|
||||
let mut filter_cmd = vec![];
|
||||
let mut filter_str: String = "".to_string();
|
||||
|
@ -111,6 +111,10 @@ pub fn play(config: Config) {
|
||||
None => break
|
||||
};
|
||||
|
||||
if !node.process.unwrap() {
|
||||
continue
|
||||
}
|
||||
|
||||
info!(
|
||||
"Play for <yellow>{}</>: <b><magenta>{}</></b>",
|
||||
sec_to_time(node.out - node.seek),
|
||||
@ -168,6 +172,8 @@ pub fn play(config: Config) {
|
||||
if let Err(e) = dec_proc.wait() {
|
||||
panic!("Decoder error: {:?}", e)
|
||||
};
|
||||
|
||||
sleep(Duration::from_secs(1));
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(1));
|
||||
|
@ -57,25 +57,14 @@ pub fn read_json(config: &Config, seek: bool) -> Playlist {
|
||||
time_sec += length_sec
|
||||
}
|
||||
|
||||
let cloned_program = playlist.program.clone();
|
||||
|
||||
for (i, item) in playlist.program.iter_mut().enumerate() {
|
||||
item.begin = Some(start_sec);
|
||||
item.index = Some(i);
|
||||
item.last_ad = Some(false);
|
||||
item.next_ad = Some(false);
|
||||
item.process = Some(true);
|
||||
let mut source_cmd: Vec<String> = vec![];
|
||||
|
||||
if i > 0 && cloned_program[i - 1].category == "advertisement".to_string() {
|
||||
item.last_ad = Some(true);
|
||||
}
|
||||
|
||||
if i + 1 < cloned_program.len() {
|
||||
if cloned_program[i + 1].category == "advertisement".to_string() {
|
||||
item.next_ad = Some(true);
|
||||
}
|
||||
}
|
||||
|
||||
if seek_first {
|
||||
let tmp_length = item.out - item.seek;
|
||||
|
||||
|
@ -2,7 +2,7 @@ use chrono::prelude::*;
|
||||
use chrono::Duration;
|
||||
use ffprobe::{ffprobe, Format, Stream};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fs::metadata, time, time::UNIX_EPOCH};
|
||||
use std::{fs::metadata, path::Path, time, time::UNIX_EPOCH};
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
@ -37,16 +37,22 @@ pub struct Media {
|
||||
pub probe: Option<MediaProbe>,
|
||||
pub last_ad: Option<bool>,
|
||||
pub next_ad: Option<bool>,
|
||||
pub process: Option<bool>,
|
||||
}
|
||||
|
||||
impl Media {
|
||||
fn new(index: usize, src: String) -> Self {
|
||||
let probe = MediaProbe::new(src.clone());
|
||||
let mut duration: f64 = 0.0;
|
||||
let mut probe = None;
|
||||
|
||||
let duration: f64 = match &probe.clone().format.unwrap().duration {
|
||||
Some(dur) => dur.parse().unwrap(),
|
||||
None => 0.0,
|
||||
};
|
||||
if Path::new("src").is_file() {
|
||||
probe = Some(MediaProbe::new(src.clone()));
|
||||
|
||||
duration = match probe.clone().unwrap().format.unwrap().duration {
|
||||
Some(dur) => dur.parse().unwrap(),
|
||||
None => 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
begin: None,
|
||||
@ -58,9 +64,10 @@ impl Media {
|
||||
source: src.clone(),
|
||||
cmd: Some(vec!["-i".to_string(), src]),
|
||||
filter: Some(vec![]),
|
||||
probe: Some(probe),
|
||||
probe: probe,
|
||||
last_ad: Some(false),
|
||||
next_ad: Some(false),
|
||||
process: Some(true),
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +77,7 @@ impl Media {
|
||||
|
||||
fn add_filter(&mut self, config: &Config) {
|
||||
let mut node = self.clone();
|
||||
self.filter = Some(filter_chains(&mut node, &config));
|
||||
self.filter = Some(filter_chains(&mut node, &config))
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +242,7 @@ pub fn get_delta(begin: &f64, config: &Config) -> (f64, f64) {
|
||||
pub fn check_sync(delta: f64, config: &Config) -> bool {
|
||||
if delta.abs() > config.general.stop_threshold && config.general.stop_threshold > 0.0 {
|
||||
error!("Start time out of sync for <yellow>{}</> seconds", delta);
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
|
@ -3,16 +3,19 @@ use std::path::Path;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::utils::{
|
||||
check_sync, gen_dummy, get_delta, json_reader::read_json, modified_time, time_to_sec, Config,
|
||||
Media,
|
||||
check_sync, gen_dummy, get_delta, get_sec, json_reader::read_json, modified_time, time_to_sec,
|
||||
Config, Media,
|
||||
};
|
||||
|
||||
use crate::filter::{overlay, Filters};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CurrentProgram {
|
||||
config: Config,
|
||||
json_mod: String,
|
||||
json_path: String,
|
||||
nodes: Vec<Media>,
|
||||
current_node: Media,
|
||||
init: bool,
|
||||
idx: usize,
|
||||
}
|
||||
@ -26,6 +29,7 @@ impl CurrentProgram {
|
||||
json_mod: json.modified.unwrap(),
|
||||
json_path: json.current_file.unwrap(),
|
||||
nodes: json.program.into(),
|
||||
current_node: Media::new(json.start_index.unwrap(), "".to_string()),
|
||||
init: true,
|
||||
idx: json.start_index.unwrap(),
|
||||
}
|
||||
@ -43,24 +47,47 @@ impl CurrentProgram {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_for_next_playlist(&mut self, node: &Media, last: bool) {
|
||||
let mut out = node.out.clone();
|
||||
fn check_for_next_playlist(&mut self, last: bool) -> f64 {
|
||||
let mut out = self.current_node.out.clone();
|
||||
let start_sec = time_to_sec(&self.config.playlist.day_start);
|
||||
let mut delta = 0.0;
|
||||
|
||||
if node.duration > node.out {
|
||||
out = node.duration.clone()
|
||||
if self.current_node.duration > self.current_node.out {
|
||||
out = self.current_node.duration.clone()
|
||||
}
|
||||
|
||||
if last {
|
||||
let seek = if node.seek > 0.0 { node.seek } else { 0.0 };
|
||||
(delta, _) = get_delta(&node.begin.unwrap().clone(), &self.config);
|
||||
let seek = if self.current_node.seek > 0.0 {
|
||||
self.current_node.seek
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
(delta, _) = get_delta(&self.current_node.begin.unwrap().clone(), &self.config);
|
||||
delta += seek + self.config.general.stop_threshold;
|
||||
}
|
||||
|
||||
let next_start = node.begin.unwrap() - start_sec + out + delta;
|
||||
let next_start = self.current_node.begin.unwrap() - start_sec + out + delta;
|
||||
|
||||
println!("{}", next_start);
|
||||
// println!("{}", next_start);
|
||||
|
||||
next_start
|
||||
}
|
||||
|
||||
fn is_ad(&mut self, i: usize, next: bool) -> Option<bool> {
|
||||
if next {
|
||||
if i + 1 < self.nodes.len() && self.nodes[i + 1].category == "advertisement".to_string()
|
||||
{
|
||||
return Some(true);
|
||||
} else {
|
||||
return Some(false);
|
||||
}
|
||||
} else {
|
||||
if i > 0 && i - 1 < self.nodes.len() && self.nodes[i - 1].category == "advertisement".to_string() {
|
||||
return Some(true);
|
||||
} else {
|
||||
return Some(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,72 +97,167 @@ impl Iterator for CurrentProgram {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.idx < self.nodes.len() {
|
||||
self.check_update();
|
||||
let mut current;
|
||||
|
||||
if self.init {
|
||||
current = handle_list_init(self.nodes[self.idx].clone(), &self.config);
|
||||
self.current_node = handle_list_init(self.nodes[self.idx].clone(), &self.config);
|
||||
self.init = false;
|
||||
} else {
|
||||
current = self.nodes[self.idx].clone();
|
||||
let new_source = timed_source(self.nodes[self.idx].clone(), &self.config, false);
|
||||
self.current_node = match new_source {
|
||||
Some(src) => src,
|
||||
None => {
|
||||
let mut media = Media::new(self.idx, "".to_string());
|
||||
media.process = Some(false);
|
||||
|
||||
let (delta, _) = get_delta(¤t.begin.unwrap(), &self.config);
|
||||
media
|
||||
}
|
||||
};
|
||||
|
||||
let (delta, _) = get_delta(&self.current_node.begin.unwrap(), &self.config);
|
||||
debug!("Delta: <yellow>{delta}</>");
|
||||
let sync = check_sync(delta, &self.config);
|
||||
|
||||
if !sync {
|
||||
current.cmd = None;
|
||||
self.current_node.cmd = None;
|
||||
|
||||
return Some(current);
|
||||
return Some(self.current_node.clone());
|
||||
}
|
||||
}
|
||||
|
||||
self.idx += 1;
|
||||
current = gen_source(current, &self.config);
|
||||
self.current_node.last_ad = self.is_ad(self.idx, false);
|
||||
self.current_node.next_ad = self.is_ad(self.idx, false);
|
||||
|
||||
self.check_for_next_playlist(¤t, true);
|
||||
Some(current)
|
||||
self.idx += 1;
|
||||
|
||||
self.check_for_next_playlist(false);
|
||||
Some(self.current_node.clone())
|
||||
} else {
|
||||
let mut current;
|
||||
let (_, time_diff) = get_delta(&get_sec(), &self.config);
|
||||
let pl_time_diff = self.check_for_next_playlist(true);
|
||||
let pl_delta = time_to_sec(&self.config.playlist.length) - pl_time_diff.abs();
|
||||
let mut last_ad = self.is_ad(self.idx, false);
|
||||
|
||||
if time_diff.abs() > pl_delta && time_diff.abs() > self.config.general.stop_threshold {
|
||||
self.current_node = Media::new(self.idx + 1, "".to_string());
|
||||
self.current_node.begin = Some(get_sec());
|
||||
let mut duration = time_diff.abs();
|
||||
|
||||
if duration > 60.0 {
|
||||
duration = 60.0;
|
||||
}
|
||||
self.current_node.duration = duration;
|
||||
self.current_node.out = duration;
|
||||
self.current_node = gen_source(self.current_node.clone(), &self.config);
|
||||
self.nodes.push(self.current_node.clone());
|
||||
|
||||
last_ad = self.is_ad(self.idx + 1, false);
|
||||
self.current_node.last_ad = last_ad;
|
||||
|
||||
|
||||
return Some(self.current_node.clone());
|
||||
}
|
||||
|
||||
let json = read_json(&self.config, false);
|
||||
self.json_mod = json.modified.unwrap();
|
||||
self.json_path = json.current_file.unwrap();
|
||||
self.nodes = json.program.into();
|
||||
self.idx = 1;
|
||||
|
||||
if self.init {
|
||||
current = handle_list_init(self.nodes[0].clone(), &self.config);
|
||||
self.current_node = handle_list_init(self.nodes[0].clone(), &self.config);
|
||||
self.init = false;
|
||||
} else {
|
||||
current = self.nodes[0].clone();
|
||||
let new_source = timed_source(self.nodes[0].clone(), &self.config, false);
|
||||
self.current_node = match new_source {
|
||||
Some(src) => src,
|
||||
None => {
|
||||
let mut media = Media::new(self.idx, "".to_string());
|
||||
media.process = Some(false);
|
||||
|
||||
let (delta, _) = get_delta(¤t.begin.unwrap(), &self.config);
|
||||
media
|
||||
}
|
||||
};
|
||||
|
||||
let (delta, _) = get_delta(&self.current_node.begin.unwrap(), &self.config);
|
||||
debug!("Delta: <yellow>{delta}</>");
|
||||
let sync = check_sync(delta, &self.config);
|
||||
|
||||
if !sync {
|
||||
current.cmd = None;
|
||||
self.current_node.cmd = None;
|
||||
|
||||
return Some(current);
|
||||
return Some(self.current_node.clone());
|
||||
}
|
||||
}
|
||||
|
||||
current = gen_source(current, &self.config);
|
||||
self.current_node.last_ad = last_ad;
|
||||
self.current_node.next_ad = self.is_ad(0, false);
|
||||
|
||||
Some(current)
|
||||
self.idx = 1;
|
||||
|
||||
Some(self.current_node.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn timed_source(node: Media, config: &Config, last: bool) -> Option<Media> {
|
||||
// prepare input clip
|
||||
// check begin and length from clip
|
||||
// return clip only if we are in 24 hours time range
|
||||
|
||||
let (delta, total_delta) = get_delta(&node.begin.unwrap(), &config);
|
||||
let mut new_node = None;
|
||||
|
||||
if config.playlist.day_start.contains(":") && config.playlist.length.contains(":") {
|
||||
debug!("Delta: <yellow>{delta}</>");
|
||||
check_sync(delta, &config);
|
||||
}
|
||||
|
||||
if (total_delta > node.out - node.seek && !last) || !config.playlist.length.contains(":") {
|
||||
// when we are in the 24 hour range, get the clip
|
||||
new_node = Some(gen_source(node, &config));
|
||||
} else if total_delta <= 0.0 {
|
||||
info!("Begin is over play time, skip: {}", node.source);
|
||||
} else if total_delta < node.duration - node.seek || last {
|
||||
println!("handle list end");
|
||||
new_node = handle_list_end(node, total_delta);
|
||||
}
|
||||
|
||||
return new_node;
|
||||
}
|
||||
|
||||
fn gen_source(mut node: Media, config: &Config) -> Media {
|
||||
if Path::new(&node.source).is_file() {
|
||||
node.add_probe();
|
||||
node.add_filter(&config);
|
||||
} else {
|
||||
error!("File not found: {}", node.source);
|
||||
let dummy = gen_dummy(node.out - node.seek, &config);
|
||||
node.source = dummy.0;
|
||||
node.cmd = Some(dummy.1);
|
||||
node.filter = Some(vec![]);
|
||||
if node.source.chars().count() == 0 {
|
||||
warn!(
|
||||
"Generate filler with <yellow>{}</> seconds length!",
|
||||
node.out - node.seek
|
||||
);
|
||||
} else {
|
||||
error!("File not found: {}", node.source);
|
||||
}
|
||||
let (source, cmd) = gen_dummy(node.out - node.seek, &config);
|
||||
node.source = source;
|
||||
node.cmd = Some(cmd);
|
||||
let mut filters = Filters::new();
|
||||
let mut chain: Vec<String> = vec![];
|
||||
overlay(&mut node, &mut filters, &config);
|
||||
|
||||
if filters.video_chain.is_some() {
|
||||
let mut filter_str: String = "".to_string();
|
||||
filter_str.push_str(filters.video_chain.unwrap().as_str());
|
||||
filter_str.push_str(filters.video_map.clone().unwrap().as_str());
|
||||
|
||||
chain.push("-filter_complex".to_string());
|
||||
chain.push(filter_str);
|
||||
chain.push("-map".to_string());
|
||||
chain.push(filters.video_map.unwrap());
|
||||
chain.push("-map".to_string());
|
||||
chain.push("1:a".to_string());
|
||||
}
|
||||
|
||||
node.filter = Some(chain);
|
||||
}
|
||||
|
||||
node
|
||||
@ -146,19 +268,18 @@ fn handle_list_init(mut node: Media, config: &Config) -> Media {
|
||||
// this we have to figure out and calculate the right length
|
||||
|
||||
debug!("Playlist init");
|
||||
println!("{:?}", node);
|
||||
|
||||
let (_, total_delta) = get_delta(&node.begin.unwrap(), config);
|
||||
|
||||
let mut out = node.out;
|
||||
|
||||
if node.out - node.seek > total_delta {
|
||||
out = total_delta + node.seek
|
||||
out = total_delta + node.seek;
|
||||
}
|
||||
|
||||
node.out = out;
|
||||
let new_node = gen_source(node, &config);
|
||||
|
||||
node
|
||||
new_node
|
||||
}
|
||||
|
||||
fn handle_list_end(mut node: Media, total_delta: f64) -> Option<Media> {
|
||||
@ -168,22 +289,33 @@ fn handle_list_end(mut node: Media, total_delta: f64) -> Option<Media> {
|
||||
|
||||
debug!("Playlist end");
|
||||
|
||||
let mut out = if node.seek > 0.0 {node.seek + total_delta} else {total_delta};
|
||||
let mut out = if node.seek > 0.0 {
|
||||
node.seek + total_delta
|
||||
} else {
|
||||
total_delta
|
||||
};
|
||||
|
||||
// prevent looping
|
||||
if out > node.duration {
|
||||
out = node.duration
|
||||
} else {
|
||||
warn!("Clip length is not in time, new duration is: <yellow>{:.2}</>", total_delta)
|
||||
warn!(
|
||||
"Clip length is not in time, new duration is: <yellow>{:.2}</>",
|
||||
total_delta
|
||||
)
|
||||
}
|
||||
|
||||
if node.duration > total_delta && total_delta > 1.0 && node.duration - node.seek >= total_delta {
|
||||
if node.duration > total_delta && total_delta > 1.0 && node.duration - node.seek >= total_delta
|
||||
{
|
||||
node.out = out;
|
||||
} else if node.duration > total_delta && total_delta < 1.0 {
|
||||
warn!("Last clip less then 1 second long, skip: {}", node.source);
|
||||
return None
|
||||
return None;
|
||||
} else {
|
||||
error!("Playlist is not long enough: <yellow>{:.2}</> seconds needed", total_delta);
|
||||
error!(
|
||||
"Playlist is not long enough: <yellow>{:.2}</> seconds needed",
|
||||
total_delta
|
||||
);
|
||||
}
|
||||
|
||||
Some(node)
|
||||
|
Loading…
Reference in New Issue
Block a user