convert text/m3u file to playlist, #195
This commit is contained in:
parent
1e01757f3b
commit
69a3e59e35
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -941,7 +941,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout"
|
||||
version = "0.15.2"
|
||||
version = "0.16.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
@ -960,7 +960,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-api"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-multipart",
|
||||
@ -990,7 +990,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-lib"
|
||||
version = "0.15.2"
|
||||
version = "0.16.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
|
@ -4,7 +4,7 @@ description = "Rest API for ffplayout"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
@ -1,31 +1,11 @@
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
io::Error,
|
||||
path::PathBuf,
|
||||
};
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::utils::{errors::ServiceError, playout_config};
|
||||
use ffplayout_lib::utils::{generate_playlist as playlist_generator, JsonPlaylist};
|
||||
|
||||
fn json_reader(path: &PathBuf) -> Result<JsonPlaylist, Error> {
|
||||
let f = File::options().read(true).write(false).open(&path)?;
|
||||
let p = serde_json::from_reader(f)?;
|
||||
|
||||
Ok(p)
|
||||
}
|
||||
|
||||
fn json_writer(path: &PathBuf, data: JsonPlaylist) -> Result<(), Error> {
|
||||
let f = File::options()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.open(&path)?;
|
||||
serde_json::to_writer_pretty(f, &data)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
use ffplayout_lib::utils::{
|
||||
generate_playlist as playlist_generator, json_reader, json_writer, JsonPlaylist,
|
||||
};
|
||||
|
||||
pub async fn read_playlist(id: i64, date: String) -> Result<JsonPlaylist, ServiceError> {
|
||||
let (config, _) = playout_config(&id).await?;
|
||||
|
@ -4,8 +4,9 @@ description = "24/7 playout based on rust and ffmpeg"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.15.2"
|
||||
version = "0.16.0"
|
||||
edition = "2021"
|
||||
default-run = "ffplayout"
|
||||
|
||||
[dependencies]
|
||||
ffplayout-lib = { path = "../lib" }
|
||||
|
@ -35,7 +35,7 @@ use ffplayout_lib::utils::{
|
||||
use utils::Args;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use ffplayout_lib::utils::{mock_time, time_now};
|
||||
use ffplayout_lib::utils::{import::import_file, mock_time, time_now};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StatusData {
|
||||
@ -93,7 +93,7 @@ fn main() {
|
||||
#[cfg(debug_assertions)]
|
||||
fake_time(&args);
|
||||
|
||||
let config = get_config(args);
|
||||
let config = get_config(args.clone());
|
||||
let config_clone = config.clone();
|
||||
let play_control = PlayerControl::new();
|
||||
let playout_stat = PlayoutStatus::new();
|
||||
@ -122,6 +122,26 @@ fn main() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if let Some(path) = args.import {
|
||||
if args.date.is_none() {
|
||||
error!("Import needs date parameter!");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// convert text/m3u file to playlist
|
||||
match import_file(&config, &args.date.unwrap(), None, &path) {
|
||||
Ok(m) => {
|
||||
info!("{m}");
|
||||
exit(0);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if config.rpc_server.enable {
|
||||
// If RPC server is enable we also fire up a JSON RPC server.
|
||||
thread::spawn(move || json_rpc_server(config_clone, play_ctl, play_stat, proc_ctl2));
|
||||
|
@ -31,6 +31,19 @@ pub struct Args {
|
||||
#[clap(short, long, help = "Play folder content")]
|
||||
pub folder: Option<String>,
|
||||
|
||||
#[clap(
|
||||
short,
|
||||
long,
|
||||
help = "Target date (YYYY-MM-DD) for text/m3u to playlist import"
|
||||
)]
|
||||
pub date: Option<String>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Import a given text/m3u file and create a playlist from it"
|
||||
)]
|
||||
pub import: Option<String>,
|
||||
|
||||
#[clap(short, long, help = "Path from playlist")]
|
||||
pub playlist: Option<String>,
|
||||
|
||||
|
@ -4,7 +4,7 @@ description = "Library for ffplayout"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.15.2"
|
||||
version = "0.16.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
78
lib/src/utils/import.rs
Normal file
78
lib/src/utils/import.rs
Normal file
@ -0,0 +1,78 @@
|
||||
/// Import text/m3u file and create a playlist out of it
|
||||
use std::{
|
||||
//error::Error,
|
||||
fs::{create_dir_all, File},
|
||||
io::{BufRead, BufReader, Error, ErrorKind},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crate::utils::{json_reader, json_serializer::JsonPlaylist, json_writer, Media, PlayoutConfig};
|
||||
|
||||
pub fn import_file(
|
||||
config: &PlayoutConfig,
|
||||
date: &str,
|
||||
channel_name: Option<String>,
|
||||
path: &str,
|
||||
) -> Result<String, Error> {
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
let mut playlist = JsonPlaylist {
|
||||
channel: channel_name.unwrap_or_else(|| "Channel 1".to_string()),
|
||||
date: date.to_string(),
|
||||
current_file: None,
|
||||
start_sec: None,
|
||||
modified: None,
|
||||
program: vec![],
|
||||
};
|
||||
|
||||
let playlist_root = Path::new(&config.playlist.path);
|
||||
if !playlist_root.is_dir() {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
format!(
|
||||
"Playlist folder <b><magenta>{}</></b> not exists!",
|
||||
&config.playlist.path,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
create_dir_all(playlist_path)?;
|
||||
|
||||
for line in reader.lines() {
|
||||
let line = line?;
|
||||
|
||||
if !line.starts_with('#') {
|
||||
let item = Media::new(0, line, true);
|
||||
|
||||
playlist.program.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
let mut file_exists = false;
|
||||
|
||||
if playlist_file.is_file() {
|
||||
file_exists = true;
|
||||
let existing_data = json_reader(playlist_file)?;
|
||||
|
||||
if playlist == existing_data {
|
||||
return Ok(format!("Playlist from {date}, already exists!"));
|
||||
}
|
||||
};
|
||||
|
||||
let mut msg = format!("Write playlist from {date} success!");
|
||||
|
||||
if file_exists {
|
||||
msg = format!("Update playlist from {date} success!");
|
||||
}
|
||||
|
||||
match json_writer(playlist_file, playlist) {
|
||||
Ok(_) => Ok(msg),
|
||||
Err(e) => Err(Error::new(ErrorKind::Other, e)),
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs::{self, metadata},
|
||||
fs::{self, metadata, File},
|
||||
io::{BufRead, BufReader, Error},
|
||||
net::TcpListener,
|
||||
path::{Path, PathBuf},
|
||||
@ -26,6 +26,7 @@ pub mod config;
|
||||
pub mod controller;
|
||||
pub mod folder;
|
||||
mod generator;
|
||||
pub mod import;
|
||||
pub mod json_serializer;
|
||||
mod json_validate;
|
||||
mod logging;
|
||||
@ -247,6 +248,24 @@ pub fn fps_calc(r_frame_rate: &str, default: f64) -> f64 {
|
||||
fps
|
||||
}
|
||||
|
||||
pub fn json_reader(path: &PathBuf) -> Result<JsonPlaylist, Error> {
|
||||
let f = File::options().read(true).write(false).open(&path)?;
|
||||
let p = serde_json::from_reader(f)?;
|
||||
|
||||
Ok(p)
|
||||
}
|
||||
|
||||
pub fn json_writer(path: &PathBuf, data: JsonPlaylist) -> Result<(), Error> {
|
||||
let f = File::options()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.open(&path)?;
|
||||
serde_json::to_writer_pretty(f, &data)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Covert JSON string to ffmpeg filter command.
|
||||
pub fn get_filter_from_json(raw_text: String) -> String {
|
||||
let re1 = Regex::new(r#""|}|\{"#).unwrap();
|
||||
|
Loading…
x
Reference in New Issue
Block a user