This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum VideoPipeline {
|
||||
Copy,
|
||||
Encode(VideoEncoder),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum VideoEncoder {
|
||||
Libx264,
|
||||
}
|
||||
|
||||
impl VideoPipeline {
|
||||
pub fn ffmpeg_args(self, segment_seconds: u8) -> Vec<String> {
|
||||
match self {
|
||||
Self::Copy => vec!["-c:v".into(), "copy".into()],
|
||||
Self::Encode(encoder) => encoder.ffmpeg_args(segment_seconds),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoEncoder {
|
||||
pub fn portable_software() -> Self {
|
||||
Self::Libx264
|
||||
}
|
||||
|
||||
fn ffmpeg_args(self, segment_seconds: u8) -> Vec<String> {
|
||||
match self {
|
||||
Self::Libx264 => vec![
|
||||
"-c:v".into(),
|
||||
"libx264".into(),
|
||||
"-preset".into(),
|
||||
"veryfast".into(),
|
||||
"-crf".into(),
|
||||
"20".into(),
|
||||
"-vf".into(),
|
||||
"scale=trunc(iw/2)*2:trunc(ih/2)*2,format=yuv420p".into(),
|
||||
"-force_key_frames".into(),
|
||||
format!("expr:gte(t,n_forced*{segment_seconds})"),
|
||||
"-sc_threshold".into(),
|
||||
"0".into(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{VideoEncoder, VideoPipeline};
|
||||
|
||||
#[test]
|
||||
fn libx264_profile_is_browser_compatible_and_segment_aligned() {
|
||||
let args = VideoPipeline::Encode(VideoEncoder::Libx264).ffmpeg_args(2);
|
||||
assert!(args.windows(2).any(|pair| pair == ["-c:v", "libx264"]));
|
||||
assert!(args.windows(2).any(|pair| pair == ["-crf", "20"]));
|
||||
assert!(
|
||||
args.windows(2)
|
||||
.any(|pair| { pair == ["-force_key_frames", "expr:gte(t,n_forced*2)"] })
|
||||
);
|
||||
assert!(args.iter().any(|arg| arg.contains("format=yuv420p")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user