1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Shared argument logic.
mod encode;
mod vmaf;
pub use encode::*;
pub use vmaf::*;
use crate::{command::encode::default_output_ext, ffprobe::Ffprobe};
use clap::Parser;
use std::{
path::{Path, PathBuf},
sync::Arc,
time::Duration,
};
/// Encoding args that apply when encoding to an output.
#[derive(Parser, Clone)]
pub struct EncodeToOutput {
/// Output file, by default the same as input with `.av1` before the extension.
///
/// E.g. if unspecified: -i vid.mkv --> vid.av1.mkv
#[arg(short, long)]
pub output: Option<PathBuf>,
/// Set the output ffmpeg audio codec.
/// By default when the input & output file extension match 'copy' is used,
/// otherwise 'libopus'.
///
/// See https://ffmpeg.org/ffmpeg.html#Audio-Options.
#[arg(long = "acodec")]
pub audio_codec: Option<String>,
/// Downmix input audio streams to stereo if input streams use greater than
/// 3 channels.
///
/// No effect if the input audio has 3 or fewer channels.
#[arg(long)]
pub downmix_to_stereo: bool,
}
/// Sampling arguments.
#[derive(Parser, Clone)]
pub struct Sample {
/// Number of 20s samples to use across the input video. Overrides --sample-every.
/// More samples take longer but may provide a more accurate result.
#[arg(long)]
pub samples: Option<u64>,
/// Calculate number of samples by dividing the input duration by this value.
/// So "12m" would mean with an input 25-36 minutes long, 3 samples would be used.
/// More samples take longer but may provide a more accurate result.
///
/// Setting --samples overrides this value.
#[arg(long, default_value = "12m", value_parser = humantime::parse_duration)]
pub sample_every: Duration,
/// Directory to store temporary sample data in.
/// Defaults to using the input's directory.
#[arg(long, env = "AB_AV1_TEMP_DIR")]
pub temp_dir: Option<PathBuf>,
/// Extension preference for encoded samples (ffmpeg encoder only).
#[arg(skip)]
pub extension: Option<Arc<str>>,
}
impl Sample {
/// Calculate the desired sample count using `samples` or `sample_every`.
pub fn sample_count(&self, input_duration: Duration) -> u64 {
if let Some(s) = self.samples {
return s;
}
(input_duration.as_secs_f64() / self.sample_every.as_secs_f64().max(1.0)).ceil() as _
}
pub fn set_extension_from_input(&mut self, input: &Path, probe: &Ffprobe) {
self.extension = Some(default_output_ext(input, probe.is_probably_an_image()).into());
}
pub fn set_extension_from_output(&mut self, output: &Path) {
self.extension = output.extension().and_then(|e| e.to_str().map(Into::into));
}
}