add simple playlist generator
This commit is contained in:
parent
614aa7851c
commit
11c577aff5
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -167,7 +167,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-rs"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
|
@ -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.9.2"
|
||||
version = "0.9.3"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@ -47,7 +47,6 @@ section = "net"
|
||||
license-file = ["LICENSE", "0"]
|
||||
depends = ""
|
||||
suggests = "ffmpeg"
|
||||
maintainer-scripts = "package/debian/"
|
||||
copyright = "Copyright (c) 2022, Jonathan Baecker. All rights reserved."
|
||||
assets = [
|
||||
["target/x86_64-unknown-linux-musl/release/ffplayout", "/usr/bin/ffplayout", "755"],
|
||||
|
@ -68,9 +68,8 @@ fn main() {
|
||||
|
||||
validate_ffmpeg();
|
||||
|
||||
if config.general.generate.is_some() {
|
||||
// generate playlist from given dates
|
||||
generate_playlist();
|
||||
if let Some(range) = config.general.generate.clone() {
|
||||
generate_playlist(range);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version,
|
||||
about = "ffplayout, Rust based 24/7 playout solution",
|
||||
about = "ffplayout, Rust based 24/7 playout solution.\n\nRun without any command to use config file only, or with commands to override parameters.",
|
||||
long_about = None)]
|
||||
pub struct Args {
|
||||
#[clap(short, long, help = "File path to ffplayout.conf")]
|
||||
@ -14,7 +14,8 @@ pub struct Args {
|
||||
#[clap(
|
||||
short,
|
||||
long,
|
||||
help = "Generate playlist for given date. Date needs format: YYYY-MM-DD. Date-range is possible to, like: 2022-01-01 - 2022-01-10.",
|
||||
help = "Generate playlist for date. Date-range is possible, like: 2022-01-01 - 2022-01-10.",
|
||||
name = "YYYY-MM-DD",
|
||||
multiple_values=true
|
||||
)]
|
||||
pub generate: Option<Vec<String>>,
|
||||
|
@ -1,4 +1,6 @@
|
||||
use std::{
|
||||
fs::{create_dir_all, write},
|
||||
path::Path,
|
||||
process::exit,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
@ -44,25 +46,59 @@ fn get_date_range(date_range: &Vec<String>) -> Vec<String> {
|
||||
range
|
||||
}
|
||||
|
||||
pub fn generate_playlist() {
|
||||
pub fn generate_playlist(mut date_range: Vec<String>) {
|
||||
let config = GlobalConfig::global();
|
||||
let mut date_range = config.general.generate.clone().unwrap();
|
||||
let total_length = config.playlist.length_sec.unwrap().clone();
|
||||
let current_list = Arc::new(Mutex::new(vec![Media::new(0, "".to_string(), false)]));
|
||||
let index = Arc::new(Mutex::new(0));
|
||||
let playlist_root = Path::new(&config.playlist.path);
|
||||
|
||||
if !playlist_root.is_dir() {
|
||||
error!(
|
||||
"Playlist folder <b><magenta>{}</></b> not exists!",
|
||||
&config.playlist.path
|
||||
);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if date_range.contains(&"-".to_string()) && date_range.len() == 3 {
|
||||
date_range = get_date_range(&date_range)
|
||||
}
|
||||
|
||||
let media_list = Source::new(current_list, index);
|
||||
let list_length = media_list.nodes.lock().unwrap().len();
|
||||
|
||||
for date in date_range {
|
||||
info!("Generate playlist for {date}");
|
||||
let d: Vec<&str> = date.split('-').collect();
|
||||
let year = d[0];
|
||||
let month = d[1];
|
||||
let playlist_path = playlist_root.join(year).join(month);
|
||||
let playlist_file = &playlist_path.join(format!("{date}.json"));
|
||||
|
||||
if let Err(e) = create_dir_all(playlist_path) {
|
||||
error!("Create folder failed: {e:?}");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if playlist_file.is_file() {
|
||||
warn!(
|
||||
"Playlist exists, skip: <b><magenta>{}</></b>",
|
||||
playlist_file.display()
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
info!(
|
||||
"Generate playlist: <b><magenta>{}</></b>",
|
||||
playlist_file.display()
|
||||
);
|
||||
|
||||
let mut filler = Media::new(0, config.storage.filler_clip.clone(), true);
|
||||
let filler_length = filler.duration.clone();
|
||||
let mut length = 0.0;
|
||||
let mut round = 0;
|
||||
|
||||
let mut playlist = Playlist {
|
||||
date,
|
||||
@ -72,33 +108,36 @@ pub fn generate_playlist() {
|
||||
program: vec![],
|
||||
};
|
||||
|
||||
let mut round = 0;
|
||||
|
||||
for item in media_list.clone() {
|
||||
let duration = item.duration.clone();
|
||||
|
||||
if total_length > length + filler_length {
|
||||
if total_length > length + duration {
|
||||
playlist.program.push(item);
|
||||
|
||||
length += duration;
|
||||
} else if filler_length > 0.0 && filler_length > total_length - length {
|
||||
println!("{filler_length}");
|
||||
filler.out = filler_length - (total_length - length);
|
||||
println!("{}", total_length - length);
|
||||
playlist.program.push(filler);
|
||||
|
||||
break;
|
||||
} else if round == 3 {
|
||||
println!("break");
|
||||
println!("length {length}");
|
||||
println!("total_length {total_length}");
|
||||
} else if round == list_length - 1 {
|
||||
break;
|
||||
} else {
|
||||
round += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("{length:?}");
|
||||
println!("{:?}", playlist.program[playlist.program.len() - 1]);
|
||||
let json: String = match serde_json::to_string_pretty(&playlist) {
|
||||
Ok(j) => j,
|
||||
Err(e) => {
|
||||
error!("Unable to serialize data: {e:?}");
|
||||
exit(0);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = write(playlist_file, &json) {
|
||||
error!("Unable to write playlist: {e:?}");
|
||||
exit(1)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ pub struct Media {
|
||||
pub out: f64,
|
||||
pub duration: f64,
|
||||
|
||||
#[serde(skip_deserializing)]
|
||||
#[serde(skip_serializing)]
|
||||
pub category: Option<String>,
|
||||
pub source: String,
|
||||
|
||||
@ -102,17 +102,19 @@ impl Media {
|
||||
}
|
||||
|
||||
pub fn add_probe(&mut self) {
|
||||
let probe = MediaProbe::new(self.source.clone());
|
||||
self.probe = Some(probe.clone());
|
||||
if self.probe.is_none() {
|
||||
let probe = MediaProbe::new(self.source.clone());
|
||||
self.probe = Some(probe.clone());
|
||||
|
||||
if self.duration == 0.0 {
|
||||
let duration = match probe.format.unwrap().duration {
|
||||
Some(dur) => dur.parse().unwrap(),
|
||||
None => 0.0,
|
||||
};
|
||||
if self.duration == 0.0 {
|
||||
let duration = match probe.format.unwrap().duration {
|
||||
Some(dur) => dur.parse().unwrap(),
|
||||
None => 0.0,
|
||||
};
|
||||
|
||||
self.out = duration;
|
||||
self.duration = duration;
|
||||
self.out = duration;
|
||||
self.duration = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user