add assets; some cmd building

This commit is contained in:
Dominic 2023-10-29 22:58:46 +01:00
parent ffad525857
commit c55906f70a
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
4 changed files with 307 additions and 3 deletions

View file

@ -2,9 +2,10 @@ use super::cmd;
use crate::time::{format_time, Time};
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
use rational::Rational;
use std::process::Command;
use std::{borrow::Cow, process::Command};
pub(crate) struct FfmpegInput {
pub(crate) concat: bool,
pub(crate) loop_input: bool,
pub(crate) fps: Option<Rational>,
pub(crate) start: Option<Time>,
@ -15,6 +16,7 @@ pub(crate) struct FfmpegInput {
impl FfmpegInput {
pub(crate) fn new(path: PathBuf) -> Self {
Self {
concat: false,
loop_input: false,
fps: None,
start: None,
@ -24,6 +26,9 @@ impl FfmpegInput {
}
fn append_to_cmd(self, cmd: &mut Command) {
if self.concat {
cmd.arg("-f").arg("concat").arg("-safe").arg("0");
}
if self.loop_input {
cmd.arg("-loop").arg("1");
}
@ -40,8 +45,65 @@ impl FfmpegInput {
}
}
pub(crate) enum Filter {
Concat {
inputs: Vec<Cow<'static, str>>,
n: usize,
output: Cow<'static, str>
},
FadeIn {
input: Cow<'static, str>,
start: Time,
duration: Time,
output: Cow<'static, str>
},
FadeOut {
input: Cow<'static, str>,
start: Time,
duration: Time,
output: Cow<'static, str>
},
Overlay {
video_input: Cow<'static, str>,
overlay_input: Cow<'static, str>,
x: Cow<'static, str>,
y: Cow<'static, str>,
output: Cow<'static, str>
},
GenerateSilence {
output: Cow<'static, str>
}
}
impl Filter {
fn is_video_filter(&self) -> bool {
matches!(
self,
Self::Concat { .. }
| Self::FadeIn { .. }
| Self::FadeOut { .. }
| Self::Overlay { .. }
)
}
fn is_audio_filter(&self) -> bool {
matches!(
self,
Self::Concat { .. }
| Self::FadeIn { .. }
| Self::FadeOut { .. }
| Self::GenerateSilence { .. }
)
}
}
pub(crate) struct Ffmpeg {
inputs: Vec<FfmpegInput>,
filters: Vec<Filter>,
output: PathBuf
}
@ -49,6 +111,7 @@ impl Ffmpeg {
pub fn new(output: PathBuf) -> Self {
Self {
inputs: Vec::new(),
filters: Vec::new(),
output
}
}
@ -57,9 +120,13 @@ impl Ffmpeg {
let mut cmd = cmd();
cmd.arg("ffmpeg").arg("-hide_banner");
// determine whether the video need to be re-encoded
let venc = self.filters.iter().any(|f| f.is_video_filter());
let aenc = self.filters.iter().any(|f| f.is_audio_filter());
// initialise a vaapi device if one exists
let vaapi_device: PathBuf = "/dev/dri/renderD128".into();
let vaapi = vaapi_device.exists();
let vaapi = venc && vaapi_device.exists();
if vaapi {
cmd.arg("-vaapi_device").arg(&vaapi_device);
}
@ -72,6 +139,20 @@ impl Ffmpeg {
// always try to synchronise audio
cmd.arg("-async").arg("1");
// TODO apply filters
// append encoding options
if vaapi {
cmd.arg("-c:v").arg("h264_vaapi");
cmd.arg("-rc_mode").arg("CQP");
cmd.arg("-global_quality").arg("22");
} else if venc {
cmd.arg("-c:v").arg("libx264");
cmd.arg("-crf").arg("22");
} else {
cmd.arg("-c:v").arg("copy");
}
unimplemented!()
}
}

View file

@ -4,6 +4,7 @@ pub mod ffmpeg;
use crate::{
iotro::intro,
render::ffmpeg::Ffmpeg,
time::{format_date, Time},
Project, ProjectSourceMetadata, Resolution
};
@ -133,6 +134,20 @@ impl<'a> Renderer<'a> {
pub(crate) fn preprocess(&self, project: &mut Project) -> anyhow::Result<()> {
assert!(!project.progress.preprocessed);
let logo = self.target.join("logo.svg");
fs::write(
&logo,
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/logo.svg"))
)?;
let fastforward = self.target.join("fastforward.svg");
fs::write(
&fastforward,
include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/assets/fastforward.svg"
))
)?;
let recording_txt = self.target.join("recording.txt");
let mut file = File::create(recording_txt)?;
for filename in &project.source.files {
@ -141,7 +156,8 @@ impl<'a> Renderer<'a> {
drop(file);
println!("\x1B[1m ==> Concatenating Video and Normalising Audio ...");
let mut ffmpeg = Ffmpeg::new();
let recording_mp4 = self.target.join("recording.mp4");
let mut ffmpeg = Ffmpeg::new(recording_mp4);
// project.source.metadata = Some(ProjectSourceMetadata {
// source_duration: ffprobe_video("format=duration", input)?.parse()?