Merge pull request #223 from jb-alvarado/master

v0.16.3
This commit is contained in:
jb-alvarado 2022-11-04 15:37:27 +01:00 committed by GitHub
commit ad37d22c01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 119 additions and 62 deletions

58
Cargo.lock generated
View File

@ -362,9 +362,9 @@ dependencies = [
[[package]]
name = "async-global-executor"
version = "2.3.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca"
checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
dependencies = [
"async-channel",
"async-executor",
@ -377,16 +377,16 @@ dependencies = [
[[package]]
name = "async-io"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7"
checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7"
dependencies = [
"async-lock",
"autocfg",
"concurrent-queue",
"futures-lite",
"libc",
"log",
"once_cell",
"parking",
"polling",
"slab",
@ -609,9 +609,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
[[package]]
name = "cc"
version = "1.0.73"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
dependencies = [
"jobserver",
]
@ -921,9 +921,9 @@ dependencies = [
[[package]]
name = "email_address"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1b32a7a2580c4473f10f66b512c34bdd7d33c5e3473227ca833abdb5afe4809"
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
[[package]]
name = "encoding_rs"
@ -962,7 +962,7 @@ dependencies = [
[[package]]
name = "ffplayout"
version = "0.16.2"
version = "0.16.3"
dependencies = [
"chrono",
"clap",
@ -982,7 +982,7 @@ dependencies = [
[[package]]
name = "ffplayout-api"
version = "0.7.0"
version = "0.7.1"
dependencies = [
"actix-files",
"actix-multipart",
@ -1012,7 +1012,7 @@ dependencies = [
[[package]]
name = "ffplayout-lib"
version = "0.16.2"
version = "0.16.3"
dependencies = [
"chrono",
"crossbeam-channel",
@ -1199,13 +1199,13 @@ dependencies = [
[[package]]
name = "futures-intrusive"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b"
checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5"
dependencies = [
"futures-core",
"lock_api",
"parking_lot 0.12.1",
"parking_lot 0.11.2",
]
[[package]]
@ -1430,9 +1430,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "hyper"
version = "0.14.20"
version = "0.14.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
checksum = "abfba89e19b959ca163c7752ba59d737c1ceea53a5d31a149c805446fc958064"
dependencies = [
"bytes",
"futures-channel",
@ -1467,9 +1467,9 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.51"
version = "0.1.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@ -1895,9 +1895,9 @@ dependencies = [
[[package]]
name = "native-tls"
version = "0.2.10"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static",
"libc",
@ -1982,9 +1982,9 @@ dependencies = [
[[package]]
name = "num_cpus"
version = "1.13.1"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"libc",
@ -2001,9 +2001,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.15.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "openssl"
@ -2039,9 +2039,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.22.0+1.1.1q"
version = "111.24.0+1.1.1s"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853"
checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd"
dependencies = [
"cc",
]
@ -2062,9 +2062,9 @@ dependencies = [
[[package]]
name = "os_str_bytes"
version = "6.3.0"
version = "6.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
[[package]]
name = "paris"

View File

@ -46,15 +46,15 @@ processing:
help_text: Default processing for all clips, to have them unique. Mode can be playlist
or folder. 'aspect' must be a float number. 'logo' is only used if the path exist.
'logo_scale' scale the logo to target size, leave it blank when no scaling
is needed, format is 'number:number', for example '100:-1' for proportional
is needed, format is 'width:height', for example '100:-1' for proportional
scaling. With 'logo_opacity' logo can become transparent. With 'audio_tracks' it
is possible to configure how many audio tracks should be processed. With 'logo_filter'
is possible to configure how many audio tracks should be processed. 'audio_channels'
can be use, if audio has more channels then only stereo. With 'logo_filter'
'overlay=W-w-12:12' you can modify the logo position. With 'use_loudnorm'
you can activate single pass EBU R128 loudness normalization, 'loudnorm_ingest'
allows normalization only on ingest stream. 'loud_*' can adjust the loudnorm
filter. With 'custom_filter' it is possible, to apply further filters.
The filter outputs should end with [c_v_out] for video filter, and [c_a_out]
for audio filter.
allows normalization only on ingest stream. 'loud_*' can adjust the loudnorm filter.
With 'custom_filter' it is possible, to apply further filters. The filter outputs
should end with [c_v_out] for video filter, and [c_a_out] for audio filter.
mode: playlist
width: 1024
height: 576
@ -66,6 +66,7 @@ processing:
logo_opacity: 0.7
logo_filter: overlay=W-w-12:12
audio_tracks: 1
audio_channels: 2
add_loudnorm: false
loudnorm_ingest: false
loud_i: -18

View File

@ -4,7 +4,7 @@ description = "Rest API for ffplayout"
license = "GPL-3.0"
authors = ["Jonathan Baecker jonbae77@gmail.com"]
readme = "README.md"
version = "0.7.0"
version = "0.7.1"
edition = "2021"
[dependencies]

View File

@ -792,7 +792,7 @@ async fn import_playlist(
obj: web::Query<ImportObj>,
) -> Result<HttpResponse, ServiceError> {
let file = Path::new(&obj.file).file_name().unwrap_or_default();
let path = env::temp_dir().join(&file).to_string_lossy().to_string();
let path = env::temp_dir().join(file).to_string_lossy().to_string();
let (config, _) = playout_config(&id).await?;
let channel = handles::select_channel(&id).await?;

View File

@ -178,7 +178,7 @@ pub async fn create_directory(
// }
fn rename(source: &PathBuf, target: &PathBuf) -> Result<MoveObject, ServiceError> {
match fs::rename(&source, &target) {
match fs::rename(source, target) {
Ok(_) => Ok(MoveObject {
source: source
.file_name()

View File

@ -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.16.2"
version = "0.16.3"
edition = "2021"
default-run = "ffplayout"

View File

@ -60,7 +60,7 @@ fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) {
let stat_file = File::options()
.read(true)
.write(false)
.open(&stat_file)
.open(stat_file)
.expect("Could not open status file");
let data: StatusData =
@ -107,20 +107,26 @@ fn main() {
exit(1);
};
if ![2, 4, 6, 8].contains(&config.processing.audio_channels) {
error!(
"Encoding {} channel(s) is not allowed. Only 2, 4, 6 and 8 channels are supported!",
config.processing.audio_channels
);
exit(1);
}
if config.general.generate.is_some() {
// run a simple playlist generator and save them to disk
if let Err(e) = generate_playlist(&config, None) {
error!("{e}");
exit(1);
};
exit(0);
}
if let Some(path) = args.import {
if args.date.is_none() {
error!("Import needs date parameter!");
exit(1);
}

View File

@ -35,7 +35,16 @@ struct TextFilter {
impl fmt::Display for TextFilter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = format!("text='{}'", self.text.clone().unwrap_or_default());
let escaped_text = self
.text
.clone()
.unwrap_or_default()
.replace('\'', "'\\\\\\''")
.replace('\\', "\\\\\\\\")
.replace('%', "\\\\\\%")
.replace(':', "\\:");
let mut s = format!("text='{escaped_text}'");
if let Some(v) = &self.x {
if !v.is_empty() {
@ -162,7 +171,7 @@ pub fn json_rpc_server(
let filter = filter_from_json(map["message"].clone());
debug!("Got drawtext command: <bright-blue>\"{filter}\"</>");
// TODO: in Rust 1.65 use let_chains instead
// TODO: in Rust 1.66 use let_chains instead
if !filter.is_empty() && config.text.zmq_stream_socket.is_some() {
if let Some(clips_filter) = playout_stat.chain.clone() {
*clips_filter.lock().unwrap() = vec![filter.clone()];

@ -1 +1 @@
Subproject commit 0994fd00d16354b3d3059e8e3fae2ed256264460
Subproject commit 6c7aec2b7f9aa71e040bfa6bd500de72074b9937

View File

@ -4,7 +4,7 @@ description = "Library for ffplayout"
license = "GPL-3.0"
authors = ["Jonathan Baecker jonbae77@gmail.com"]
readme = "README.md"
version = "0.16.2"
version = "0.16.3"
edition = "2021"
[dependencies]

View File

@ -274,7 +274,7 @@ fn fade(node: &mut Media, chain: &mut Filters, nr: i32, filter_type: FilterType)
chain.add_filter(&format!("{t}fade=in:st=0:d=0.5"), nr, filter_type)
}
if node.out != node.duration && node.out - node.seek - 1.0 > 0.0 {
if node.out != node.duration && node.out - node.seek > 1.0 {
chain.add_filter(
&format!("{t}fade=out:st={}:d=1.0", (node.out - node.seek - 1.0)),
nr,

View File

@ -25,7 +25,7 @@ pub fn filter_node(
_ => config.text.zmq_stream_socket.clone(),
};
// TODO: in Rust 1.65 use let_chains instead
// TODO: in Rust 1.66 use let_chains instead
if config.text.text_from_filename && node.is_some() {
let source = node.unwrap_or(&Media::new(0, "", false)).source.clone();
let text = match Regex::new(&config.text.regex)
@ -40,11 +40,11 @@ pub fn filter_node(
.to_string(),
};
let escape = text
let escaped_text = text
.replace('\'', "'\\\\\\''")
.replace('%', "\\\\\\%")
.replace(':', "\\:");
filter = format!("drawtext=text='{escape}':{}{font}", config.text.style)
filter = format!("drawtext=text='{escaped_text}':{}{font}", config.text.style)
} else if let Some(socket) = zmq_socket {
let mut filter_cmd = format!("text=''{font}");

View File

@ -19,8 +19,9 @@ pub const IMAGE_FORMAT: [&str; 21] = [
];
// Some well known errors can be safely ignore
pub const FFMPEG_IGNORE_ERRORS: [&str; 9] = [
pub const FFMPEG_IGNORE_ERRORS: [&str; 10] = [
"ac-tex damaged",
"codec s302m, is muxed as a private data stream",
"corrupt decoded frame in stream",
"corrupt input packet in stream",
"end mismatch left",
@ -157,8 +158,10 @@ pub struct Processing {
pub logo_scale: String,
pub logo_opacity: f32,
pub logo_filter: String,
#[serde(default)]
#[serde(default = "default_tracks")]
pub audio_tracks: i32,
#[serde(default = "default_channels")]
pub audio_channels: u8,
pub add_loudnorm: bool,
pub loudnorm_ingest: bool,
pub loud_i: f32,
@ -242,6 +245,14 @@ pub struct Out {
pub output_cmd: Option<Vec<String>>,
}
fn default_tracks() -> i32 {
1
}
fn default_channels() -> u8 {
2
}
impl PlayoutConfig {
/// Read config from YAML file, and set some extra config values.
pub fn new(cfg_path: Option<String>) -> Self {
@ -299,7 +310,12 @@ impl PlayoutConfig {
config.processing.width * config.processing.height / 16
);
config.processing.cmd = Some(vec_strings![
let buff_size = format!(
"{}k",
(config.processing.width * config.processing.height / 16) / 2
);
let mut process_cmd = vec_strings![
"-pix_fmt",
"yuv420p",
"-r",
@ -315,20 +331,25 @@ impl PlayoutConfig {
"-maxrate",
&bitrate,
"-bufsize",
&bitrate,
"-c:a",
"mp2",
"-b:a",
"384k",
&buff_size
];
process_cmd.append(&mut pre_audio_codec(
config.processing.add_loudnorm,
config.processing.loudnorm_ingest,
));
process_cmd.append(&mut vec_strings![
"-ar",
"48000",
"-ac",
"2",
config.processing.audio_channels,
"-f",
"mpegts",
"-"
]);
config.processing.cmd = Some(process_cmd);
config.ingest.input_cmd = split(config.ingest.input_param.as_str());
config.out.output_count = 1;
@ -380,3 +401,16 @@ impl Default for PlayoutConfig {
Self::new(None)
}
}
/// When add_loudnorm is False we use a different audio encoder,
/// s302m has higher quality, but is experimental
/// and works not well together with the loudnorm filter.
fn pre_audio_codec(add_loudnorm: bool, loudnorm_ingest: bool) -> Vec<String> {
let mut codec = vec_strings!["-c:a", "s302m", "-strict", "-2", "-sample_fmt", "s16"];
if add_loudnorm || loudnorm_ingest {
codec = vec_strings!["-c:a", "mp2", "-b:a", "384k"];
}
codec
}

View File

@ -265,7 +265,7 @@ pub fn fps_calc(r_frame_rate: &str, default: f64) -> f64 {
}
pub fn json_reader(path: &PathBuf) -> Result<JsonPlaylist, Error> {
let f = File::options().read(true).write(false).open(&path)?;
let f = File::options().read(true).write(false).open(path)?;
let p = serde_json::from_reader(f)?;
Ok(p)
@ -276,7 +276,7 @@ pub fn json_writer(path: &PathBuf, data: JsonPlaylist) -> Result<(), Error> {
.write(true)
.truncate(true)
.create(true)
.open(&path)?;
.open(path)?;
serde_json::to_writer_pretty(f, &data)?;
Ok(())

View File

@ -54,8 +54,15 @@ for target in "${targets[@]}"; do
if [[ -f "ffplayout-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-v${version}_${target}.tar.gz"
fi
c_cc="x86_64-apple-darwin20.4-clang"
c_cxx="x86_64-apple-darwin20.4-clang++"
CC="x86_64-apple-darwin20.4-cc" cargo build --release --target=$target
if [[ $target == "aarch64-apple-darwin" ]]; then
c_cc="aarch64-apple-darwin20.4-clang"
c_cxx="aarch64-apple-darwin20.4-clang++"
fi
CC="$c_cc" CXX="$c_cxx" cargo build --release --target=$target
cp ./target/${target}/release/ffpapi .
cp ./target/${target}/release/ffplayout .