add stream copy mode, fix #324

This commit is contained in:
jb-alvarado 2023-07-25 21:26:19 +02:00
parent a739a9f670
commit b44efde8f1
5 changed files with 80 additions and 45 deletions

View File

@ -47,6 +47,7 @@ Check the [releases](https://github.com/ffplayout/ffplayout/releases/latest) for
- image source (will loop until out duration is reached)
- extra audio source, has priority over audio from video (experimental *)
- [multiple audio tracks](/docs/multi_audio.md) (experimental *)
- stream copy mode (experimental *)
- [custom filters](/docs/custom_filters.md) globally in config, or in playlist for specific clips
- import playlist from text or m3u file, with CLI or frontend
- audio only, for radio mode (experimental *)

View File

@ -57,6 +57,8 @@ processing:
[c_v_out] for video filter, and [c_a_out] for audio filter.
mode: playlist
audio_only: false
copy_audio: true
copy_video: false
width: 1024
height: 576
aspect: 1.778

View File

@ -177,6 +177,12 @@ pub fn write_hls(
);
let mut enc_prefix = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format];
if config.processing.copy_video
|| (!config.processing.audio_only && config.processing.copy_audio)
{
enc_prefix.push("-re".to_string());
}
enc_prefix.append(&mut cmd);
let enc_cmd = prepare_output_cmd(config, enc_prefix, &node.filter);

View File

@ -518,7 +518,7 @@ pub fn filter_chains(
return filters;
}
if !config.processing.audio_only {
if !config.processing.audio_only && !config.processing.copy_video {
if let Some(probe) = node.probe.as_ref() {
if Path::new(&node.audio).is_file() {
filters.audio_position = 1;
@ -560,42 +560,44 @@ pub fn filter_chains(
let (list_vf, list_af) = custom::filter_node(&node.custom_filter);
if config.processing.audio_only {
if config.processing.audio_only && !config.processing.copy_audio {
realtime(node, &mut filters, config, Audio);
} else {
} else if !config.processing.copy_video {
custom(&proc_vf, &mut filters, 0, Video);
custom(&list_vf, &mut filters, 0, Video);
}
for i in 0..config.processing.audio_tracks {
if node
.probe
.as_ref()
.and_then(|p| p.audio_streams.get(i as usize))
.is_some()
|| Path::new(&node.audio).is_file()
{
extend_audio(node, &mut filters, i);
} else if node.unit == Decoder {
if !node.source.contains("color=c=") {
warn!(
"Missing audio track (id {i}) from <b><magenta>{}</></b>",
node.source
);
if !config.processing.copy_audio {
for i in 0..config.processing.audio_tracks {
if node
.probe
.as_ref()
.and_then(|p| p.audio_streams.get(i as usize))
.is_some()
|| Path::new(&node.audio).is_file()
{
extend_audio(node, &mut filters, i);
} else if node.unit == Decoder {
if !node.source.contains("color=c=") {
warn!(
"Missing audio track (id {i}) from <b><magenta>{}</></b>",
node.source
);
}
add_audio(node, &mut filters, i);
}
add_audio(node, &mut filters, i);
// add at least anull filter, for correct filter construction,
// is important for split filter in HLS mode
filters.add_filter("anull", i, Audio);
fade(node, &mut filters, i, Audio);
audio_volume(&mut filters, config, i);
custom(&proc_af, &mut filters, i, Audio);
custom(&list_af, &mut filters, i, Audio);
}
// add at least anull filter, for correct filter construction,
// is important for split filter in HLS mode
filters.add_filter("anull", i, Audio);
fade(node, &mut filters, i, Audio);
audio_volume(&mut filters, config, i);
custom(&proc_af, &mut filters, i, Audio);
custom(&list_af, &mut filters, i, Audio);
}
if config.out.mode == HLS {

View File

@ -213,6 +213,10 @@ pub struct Processing {
pub mode: ProcessMode,
#[serde(default)]
pub audio_only: bool,
#[serde(default)]
pub copy_audio: bool,
#[serde(default)]
pub copy_video: bool,
pub width: i64,
pub height: i64,
pub aspect: f64,
@ -406,6 +410,8 @@ impl PlayoutConfig {
if config.processing.audio_only {
process_cmd.append(&mut vec_strings!["-vn"]);
} else if config.processing.copy_video {
process_cmd.append(&mut vec_strings!["-c:v", "copy"]);
} else {
process_cmd.append(&mut vec_strings![
"-pix_fmt",
@ -427,19 +433,17 @@ impl PlayoutConfig {
]);
}
process_cmd.append(&mut pre_audio_codec(
&config.processing.custom_filter,
&config.ingest.custom_filter,
));
process_cmd.append(&mut vec_strings![
"-ar",
"48000",
"-ac",
config.processing.audio_channels,
"-f",
"mpegts",
"-"
]);
if config.processing.copy_audio {
process_cmd.append(&mut vec_strings!["-c:a", "copy"]);
} else {
process_cmd.append(&mut pre_audio_codec(
&config.processing.custom_filter,
&config.ingest.custom_filter,
config.processing.audio_channels,
));
}
process_cmd.append(&mut vec_strings!["-f", "mpegts", "-"]);
config.processing.cmd = Some(process_cmd);
@ -498,11 +502,31 @@ impl Default for PlayoutConfig {
/// When custom_filter contains loudnorm filter 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(proc_filter: &str, ingest_filter: &str) -> Vec<String> {
let mut codec = vec_strings!["-c:a", "s302m", "-strict", "-2", "-sample_fmt", "s16"];
fn pre_audio_codec(proc_filter: &str, ingest_filter: &str, channel_count: u8) -> Vec<String> {
let mut codec = vec_strings![
"-c:a",
"s302m",
"-strict",
"-2",
"-sample_fmt",
"s16",
"-ar",
"48000",
"-ac",
channel_count
];
if proc_filter.contains("loudnorm") || ingest_filter.contains("loudnorm") {
codec = vec_strings!["-c:a", "mp2", "-b:a", "384k"];
codec = vec_strings![
"-c:a",
"mp2",
"-b:a",
"384k",
"-ar",
"48000",
"-ac",
channel_count
];
}
codec