commit
a195703e27
48
Cargo.lock
generated
48
Cargo.lock
generated
@ -79,9 +79,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.1.6"
|
version = "3.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123"
|
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
@ -96,9 +96,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "3.1.4"
|
version = "3.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16"
|
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
@ -132,6 +132,15 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email-encoding"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6690291166824e467790ac08ba42f241791567e8337bbf00c5a6e87889629f98"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
@ -143,7 +152,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffplayout-rs"
|
name = "ffplayout-rs"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
@ -355,9 +364,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -431,11 +440,12 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.10.0-rc.4"
|
version = "0.10.0-rc.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71d8da8f34d086b081c9cc3b57d3bb3b51d16fc06b5c848a188e2f14d58ac2a5"
|
checksum = "5144148f337be14dabfc0f0d85b691a68ac6c77ef22a5c47c5504b70a7c9fcf3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
|
"email-encoding",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hostname",
|
"hostname",
|
||||||
@ -555,9 +565,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "native-tls"
|
name = "native-tls"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09bf6f32a3afefd0b587ee42ed19acd945c6d1f3b5424040f50b2f24ab16be77"
|
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
@ -717,9 +727,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
@ -817,9 +827,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.12"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0"
|
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
@ -961,9 +971,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
@ -973,9 +983,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.89"
|
version = "1.0.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54"
|
checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ffplayout-rs"
|
name = "ffplayout-rs"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -8,7 +8,7 @@ chrono = "0.4"
|
|||||||
clap = { version = "3.1", features = ["derive"] }
|
clap = { version = "3.1", features = ["derive"] }
|
||||||
ffprobe = "0.3"
|
ffprobe = "0.3"
|
||||||
file-rotate = "0.6"
|
file-rotate = "0.6"
|
||||||
lettre = "0.10.0-rc.4"
|
lettre = "0.10.0-rc.5"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
notify = "4.0"
|
notify = "4.0"
|
||||||
once_cell = "1.10"
|
once_cell = "1.10"
|
||||||
|
21
README.md
21
README.md
@ -40,6 +40,7 @@ The main purpose of ffplayout is to provide a 24/7 broadcasting solution that pl
|
|||||||
- output:
|
- output:
|
||||||
- **stream**
|
- **stream**
|
||||||
- **desktop**
|
- **desktop**
|
||||||
|
- **HLS**
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
-----
|
-----
|
||||||
@ -105,6 +106,26 @@ But be careful with it, better test it multiple times!
|
|||||||
|
|
||||||
More informations in [Wiki](https://github.com/ffplayout/ffplayout_engine/wiki/Remote-URL-Source)
|
More informations in [Wiki](https://github.com/ffplayout/ffplayout_engine/wiki/Remote-URL-Source)
|
||||||
|
|
||||||
|
HLS output
|
||||||
|
-----
|
||||||
|
|
||||||
|
For outputting to HLS, output parameters should look like:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
out:
|
||||||
|
...
|
||||||
|
|
||||||
|
output_param: >-
|
||||||
|
...
|
||||||
|
|
||||||
|
-flags +cgop
|
||||||
|
-f hls
|
||||||
|
-hls_time 6
|
||||||
|
-hls_list_size 600
|
||||||
|
-hls_flags append_list+delete_segments+omit_endlist+program_date_time
|
||||||
|
-hls_segment_filename /var/www/html/live/stream-%09d.ts /var/www/html/live/stream.m3u8
|
||||||
|
```
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@ impl CurrentProgram {
|
|||||||
|
|
||||||
self.json_mod = json.modified;
|
self.json_mod = json.modified;
|
||||||
self.nodes = json.program;
|
self.nodes = json.program;
|
||||||
|
|
||||||
|
self.get_current_clip();
|
||||||
|
self.index += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
@ -159,28 +162,43 @@ impl CurrentProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_init_clip(&mut self) {
|
fn get_current_time(&mut self) -> f64 {
|
||||||
let mut time_sec = get_sec();
|
let mut time_sec = get_sec();
|
||||||
|
|
||||||
if time_sec < self.start_sec {
|
if time_sec < self.start_sec {
|
||||||
time_sec += self.config.playlist.length_sec.unwrap()
|
time_sec += self.config.playlist.length_sec.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_sec
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_current_clip(&mut self) {
|
||||||
|
let time_sec = self.get_current_time();
|
||||||
|
|
||||||
for (i, item) in self.nodes.iter_mut().enumerate() {
|
for (i, item) in self.nodes.iter_mut().enumerate() {
|
||||||
if item.begin.unwrap() + item.out - item.seek > time_sec {
|
if item.begin.unwrap() + item.out - item.seek > time_sec {
|
||||||
*self.init.lock().unwrap() = false;
|
*self.init.lock().unwrap() = false;
|
||||||
self.index = i + 1;
|
self.index = i;
|
||||||
|
|
||||||
// de-instance node to preserve original values in list
|
|
||||||
let mut node_clone = item.clone();
|
|
||||||
node_clone.seek = time_sec - node_clone.begin.unwrap();
|
|
||||||
|
|
||||||
self.current_node = handle_list_init(node_clone);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_clip(&mut self) {
|
||||||
|
self.get_current_clip();
|
||||||
|
|
||||||
|
if !*self.init.lock().unwrap() {
|
||||||
|
let time_sec = self.get_current_time();
|
||||||
|
|
||||||
|
// de-instance node to preserve original values in list
|
||||||
|
let mut node_clone = self.nodes[self.index].clone();
|
||||||
|
self.index += 1;
|
||||||
|
|
||||||
|
node_clone.seek = time_sec - node_clone.begin.unwrap();
|
||||||
|
self.current_node = handle_list_init(node_clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for CurrentProgram {
|
impl Iterator for CurrentProgram {
|
||||||
@ -192,7 +210,7 @@ impl Iterator for CurrentProgram {
|
|||||||
self.check_update(true);
|
self.check_update(true);
|
||||||
|
|
||||||
if self.json_path.is_some() {
|
if self.json_path.is_some() {
|
||||||
self.get_init_clip();
|
self.init_clip();
|
||||||
}
|
}
|
||||||
|
|
||||||
if *self.init.lock().unwrap() {
|
if *self.init.lock().unwrap() {
|
||||||
@ -209,7 +227,7 @@ impl Iterator for CurrentProgram {
|
|||||||
>= self.config.playlist.length_sec.unwrap()
|
>= self.config.playlist.length_sec.unwrap()
|
||||||
+ self.config.playlist.start_sec.unwrap()
|
+ self.config.playlist.start_sec.unwrap()
|
||||||
{
|
{
|
||||||
self.get_init_clip();
|
self.init_clip();
|
||||||
} else {
|
} else {
|
||||||
let mut current_time = get_sec();
|
let mut current_time = get_sec();
|
||||||
let (_, total_delta) = get_delta(¤t_time);
|
let (_, total_delta) = get_delta(¤t_time);
|
||||||
|
@ -10,7 +10,7 @@ use tokio::runtime::Handle;
|
|||||||
|
|
||||||
use crate::utils::{get_date, modified_time, validate_playlist, GlobalConfig, Media};
|
use crate::utils::{get_date, modified_time, validate_playlist, GlobalConfig, Media};
|
||||||
|
|
||||||
pub const DUMMY_LEN: f64 = 20.0;
|
pub const DUMMY_LEN: f64 = 60.0;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Playlist {
|
pub struct Playlist {
|
||||||
@ -62,6 +62,7 @@ pub fn read_json(
|
|||||||
let mut current_file: String = playlist_path.as_path().display().to_string();
|
let mut current_file: String = playlist_path.as_path().display().to_string();
|
||||||
|
|
||||||
if let Some(p) = path {
|
if let Some(p) = path {
|
||||||
|
playlist_path = Path::new(&p).to_owned();
|
||||||
current_file = p
|
current_file = p
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,11 @@ pub fn read_json(
|
|||||||
|
|
||||||
info!("Read Playlist: <b><magenta>{}</></b>", ¤t_file);
|
info!("Read Playlist: <b><magenta>{}</></b>", ¤t_file);
|
||||||
|
|
||||||
let f = File::open(¤t_file).expect("Could not open json playlist file.");
|
let f = File::options()
|
||||||
|
.read(true)
|
||||||
|
.write(false)
|
||||||
|
.open(¤t_file)
|
||||||
|
.expect("Could not open json playlist file.");
|
||||||
let mut playlist: Playlist =
|
let mut playlist: Playlist =
|
||||||
serde_json::from_reader(f).expect("Could not read json playlist file.");
|
serde_json::from_reader(f).expect("Could not read json playlist file.");
|
||||||
|
|
||||||
|
@ -6,14 +6,16 @@ use crate::utils::{sec_to_time, GlobalConfig, MediaProbe, Playlist};
|
|||||||
|
|
||||||
pub async fn validate_playlist(playlist: Playlist, is_terminated: Arc<Mutex<bool>>, config: GlobalConfig) {
|
pub async fn validate_playlist(playlist: Playlist, is_terminated: Arc<Mutex<bool>>, config: GlobalConfig) {
|
||||||
let date = playlist.date;
|
let date = playlist.date;
|
||||||
let length = config.playlist.length_sec.unwrap();
|
let mut length = config.playlist.length_sec.unwrap();
|
||||||
let mut start_sec = 0.0;
|
let mut begin = config.playlist.start_sec.unwrap();
|
||||||
|
|
||||||
|
length += begin;
|
||||||
|
|
||||||
debug!("validate playlist from: <yellow>{date}</>");
|
debug!("validate playlist from: <yellow>{date}</>");
|
||||||
|
|
||||||
for item in playlist.program.iter() {
|
for item in playlist.program.iter() {
|
||||||
if *is_terminated.lock().unwrap() {
|
if *is_terminated.lock().unwrap() {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Path::new(&item.source).is_file() {
|
if Path::new(&item.source).is_file() {
|
||||||
@ -22,25 +24,25 @@ pub async fn validate_playlist(playlist: Playlist, is_terminated: Arc<Mutex<bool
|
|||||||
if probe.format.is_none() {
|
if probe.format.is_none() {
|
||||||
error!(
|
error!(
|
||||||
"No Metadata from file <b><magenta>{}</></b> at <yellow>{}</>",
|
"No Metadata from file <b><magenta>{}</></b> at <yellow>{}</>",
|
||||||
sec_to_time(start_sec),
|
sec_to_time(begin),
|
||||||
item.source
|
item.source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"File on position <yellow>{}</> not exists: <b><magenta>{}</></b>",
|
"File on position <yellow>{}</> not exists: <b><magenta>{}</></b>",
|
||||||
sec_to_time(start_sec),
|
sec_to_time(begin),
|
||||||
item.source
|
item.source
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_sec += item.out - item.seek;
|
begin += item.out - item.seek;
|
||||||
}
|
}
|
||||||
|
|
||||||
if length > start_sec + 1.0 && !*is_terminated.lock().unwrap() {
|
if length > begin + 1.0 {
|
||||||
error!(
|
error!(
|
||||||
"Playlist from <yellow>{date}</> not long enough, <yellow>{}</> needed!",
|
"Playlist from <yellow>{date}</> not long enough, <yellow>{}</> needed!",
|
||||||
sec_to_time(length - start_sec),
|
sec_to_time(length - begin),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,10 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use file_rotate::{compression::Compression, suffix::AppendCount, ContentLimit, FileRotate};
|
use file_rotate::{compression::Compression, suffix::AppendCount, ContentLimit, FileRotate};
|
||||||
use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
|
use lettre::{
|
||||||
|
message::header, transport::smtp::authentication::Credentials, Message, SmtpTransport,
|
||||||
|
Transport,
|
||||||
|
};
|
||||||
use log::{Level, LevelFilter, Log, Metadata, Record};
|
use log::{Level, LevelFilter, Log, Metadata, Record};
|
||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
@ -24,6 +27,7 @@ fn send_mail(msg: String) {
|
|||||||
.from(config.mail.sender_addr.parse().unwrap())
|
.from(config.mail.sender_addr.parse().unwrap())
|
||||||
.to(config.mail.recipient.parse().unwrap())
|
.to(config.mail.recipient.parse().unwrap())
|
||||||
.subject(config.mail.subject.clone())
|
.subject(config.mail.subject.clone())
|
||||||
|
.header(header::ContentType::TEXT_PLAIN)
|
||||||
.body(clean_string(msg.clone()))
|
.body(clean_string(msg.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -79,7 +83,11 @@ pub struct LogMailer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LogMailer {
|
impl LogMailer {
|
||||||
pub fn new(log_level: LevelFilter, config: Config, messages: Arc<Mutex<Vec<String>>>) -> Box<LogMailer> {
|
pub fn new(
|
||||||
|
log_level: LevelFilter,
|
||||||
|
config: Config,
|
||||||
|
messages: Arc<Mutex<Vec<String>>>,
|
||||||
|
) -> Box<LogMailer> {
|
||||||
Box::new(LogMailer {
|
Box::new(LogMailer {
|
||||||
level: log_level,
|
level: log_level,
|
||||||
config,
|
config,
|
||||||
@ -97,10 +105,16 @@ impl Log for LogMailer {
|
|||||||
if self.enabled(record.metadata()) {
|
if self.enabled(record.metadata()) {
|
||||||
match record.level() {
|
match record.level() {
|
||||||
Level::Error => {
|
Level::Error => {
|
||||||
self.messages.lock().unwrap().push(record.args().to_string());
|
self.messages
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push(record.args().to_string());
|
||||||
}
|
}
|
||||||
Level::Warn => {
|
Level::Warn => {
|
||||||
self.messages.lock().unwrap().push(record.args().to_string());
|
self.messages
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push(record.args().to_string());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@ -201,10 +215,7 @@ pub fn init_logging(
|
|||||||
let mut filter = LevelFilter::Error;
|
let mut filter = LevelFilter::Error;
|
||||||
let messages: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
let messages: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
|
||||||
rt_handle.spawn(mail_queue(
|
rt_handle.spawn(mail_queue(messages.clone(), is_terminated.clone()));
|
||||||
messages.clone(),
|
|
||||||
is_terminated.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let mail_config = log_config
|
let mail_config = log_config
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -292,13 +292,11 @@ pub fn seek_and_length(src: String, seek: f64, out: f64, duration: f64) -> Vec<S
|
|||||||
source_cmd.append(&mut vec![
|
source_cmd.append(&mut vec![
|
||||||
"-ss".to_string(),
|
"-ss".to_string(),
|
||||||
format!("{}", seek).to_string(),
|
format!("{}", seek).to_string(),
|
||||||
"-i".to_string(),
|
|
||||||
src.clone(),
|
|
||||||
])
|
])
|
||||||
} else {
|
|
||||||
source_cmd.append(&mut vec!["-i".to_string(), src.clone()])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_cmd.append(&mut vec!["-i".to_string(), src]);
|
||||||
|
|
||||||
if duration > out {
|
if duration > out {
|
||||||
source_cmd.append(&mut vec![
|
source_cmd.append(&mut vec![
|
||||||
"-t".to_string(),
|
"-t".to_string(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user