Skip to content
Snippets Groups Projects
Unverified Commit feb8596b authored by Dominic Meiser's avatar Dominic Meiser
Browse files

support rescaling

parent 268c4b3a
No related branches found
No related tags found
No related merge requests found
...@@ -37,43 +37,58 @@ struct Args { ...@@ -37,43 +37,58 @@ struct Args {
mem_limit: String mem_limit: String
} }
macro_rules! resolutions {
($($res:ident: $width:literal x $height:literal at $bitrate:literal),+) => {
#[allow(non_camel_case_types, clippy::upper_case_acronyms)] #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Clone, Copy, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)] #[derive(Clone, Copy, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
enum Resolution { enum Resolution {
/// 640x360 $(
nHD, #[doc = concat!(stringify!($width), "x", stringify!($height))]
/// 1280x720 $res
HD, ),+
/// 1920x1080
FullHD,
/// 2560x1440
WQHD,
/// 3840x2160
UHD
} }
const NUM_RESOLUTIONS: usize = {
let mut num = 0;
$(num += 1; stringify!($res);)+
num
};
impl Resolution { impl Resolution {
fn values() -> [Self; NUM_RESOLUTIONS] {
[$(Self::$res),+]
}
fn width(self) -> usize { fn width(self) -> usize {
match self { match self {
Self::nHD => 640, $(Self::$res => $width),+
Self::HD => 1280,
Self::FullHD => 1920,
Self::WQHD => 2560,
Self::UHD => 3840
} }
} }
fn height(self) -> usize { fn height(self) -> usize {
match self { match self {
Self::nHD => 360, $(Self::$res => $height),+
Self::HD => 720, }
Self::FullHD => 1080, }
Self::WQHD => 1440,
Self::UHD => 2160 fn bitrate(self) -> &'static str {
match self {
$(Self::$res => $bitrate),+
}
}
} }
} }
} }
resolutions! {
nHD: 640 x 360 at "500k",
HD: 1280 x 720 at "1M",
FullHD: 1920 x 1080 at "2M",
WQHD: 2560 x 1440 at "3M",
// TODO qsx muss mal sagen wieviel bitrate für 4k
UHD: 3840 x 2160 at "4M"
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
struct Project { struct Project {
lecture: ProjectLecture, lecture: ProjectLecture,
...@@ -245,6 +260,38 @@ fn main() { ...@@ -245,6 +260,38 @@ fn main() {
fs::write(&project_path, toml::to_string(&project).unwrap().as_bytes()).unwrap(); fs::write(&project_path, toml::to_string(&project).unwrap().as_bytes()).unwrap();
} }
// render the video
let mut videos = Vec::new();
videos.push(if !project.progress.rendered {
let video = renderer.render(&mut project).unwrap(); let video = renderer.render(&mut project).unwrap();
println!("\x1B[1m ==> DONE :)\x1B[0m Video: {video}"); project.progress.rendered = true;
println!("{}", toml::to_string(&project).unwrap());
fs::write(&project_path, toml::to_string(&project).unwrap().as_bytes()).unwrap();
video
} else {
renderer.video_mp4(&project)
});
// rescale the video
for res in Resolution::values() {
if res >= project.source.metadata.as_ref().unwrap().source_res {
continue;
}
if !project.progress.transcoded.contains(&res) {
videos.push(renderer.rescale(res, &project).unwrap());
project.progress.transcoded.insert(res);
println!("{}", toml::to_string(&project).unwrap());
fs::write(&project_path, toml::to_string(&project).unwrap().as_bytes())
.unwrap();
}
}
println!("\x1B[1m ==> DONE :)\x1B[0m");
println!(" Videos:");
for v in &videos {
println!(" -> {v}");
}
} }
...@@ -261,18 +261,17 @@ impl<'a> Renderer<'a> { ...@@ -261,18 +261,17 @@ impl<'a> Renderer<'a> {
Ok(()) Ok(())
} }
fn video_mp4_res(&self, res: Resolution) -> PathBuf {
self.target
.join(format!("{}-{}p.mp4", self.slug, res.height()))
}
pub(crate) fn video_mp4(&self, project: &Project) -> PathBuf {
self.video_mp4_res(project.source.metadata.as_ref().unwrap().source_res)
}
pub(crate) fn render(&self, project: &mut Project) -> anyhow::Result<PathBuf> { pub(crate) fn render(&self, project: &mut Project) -> anyhow::Result<PathBuf> {
let mut output = self.target.join(format!( let output = self.video_mp4(project);
"{}-{}p.mp4",
self.slug,
project
.source
.metadata
.as_ref()
.unwrap()
.source_res
.height()
));
let mut ffmpeg = Ffmpeg::new(output.clone()); let mut ffmpeg = Ffmpeg::new(output.clone());
// add all of our inputs // add all of our inputs
...@@ -435,4 +434,37 @@ impl<'a> Renderer<'a> { ...@@ -435,4 +434,37 @@ impl<'a> Renderer<'a> {
Ok(output) Ok(output)
} }
pub fn rescale(&self, res: Resolution, project: &Project) -> anyhow::Result<PathBuf> {
let input = self.video_mp4(project);
let output = self.video_mp4_res(res);
println!("\x1B[1m ==> Rescaling to {}p\x1B[0m", res.height());
let mut ffmpeg = cmd();
ffmpeg.arg("ffmpeg").arg("-hide_banner");
// TODO do we just always want hwaccel?
ffmpeg
.arg("-hwaccel")
.arg("vaapi")
.arg("-hwaccel_device")
.arg("/dev/dri/renderD128")
.arg("-hwaccel_output_format")
.arg("vaapi");
ffmpeg.arg("-i").arg(input);
ffmpeg.arg("-vf").arg(format!(
"scale_vaapi=w={}:h={}",
res.width(),
res.height()
));
ffmpeg.arg("-c:a").arg("copy").arg("-c:v").arg("h264_vaapi");
ffmpeg.arg("-b:v").arg(res.bitrate());
ffmpeg.arg(&output);
let status = ffmpeg.status()?;
if status.success() {
Ok(output)
} else {
bail!("ffmpeg failed with exit code {:?}", status.code())
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment