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

8
assets/fastforward.svg Normal file
View file

@ -0,0 +1,8 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
<path d="m8 2v12l7-6zm-7 0v12l7-6z" class="ColorScheme-Text" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 287 B

199
assets/logo.svg Normal file
View file

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="299.99982"
height="300.00003"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docbase="C:\Eigene Dateien\Video AG"
sodipodi:docname="logo.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.0"
inkscape:export-filename="Q:\video AG\fs-pub-video\folien\logo-1024.png"
inkscape:export-xdpi="307.20001"
inkscape:export-ydpi="307.20001">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective21" />
<linearGradient
id="linearGradient2041">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.00000000"
id="stop2043" />
<stop
style="stop-color:#7d7d7d;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop2045" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2041"
id="linearGradient2047"
x1="194.17578"
y1="139.59265"
x2="250.03906"
y2="139.59265"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(317,-57)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.4889823"
inkscape:cx="71.681092"
inkscape:cy="217.8489"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:window-width="1400"
inkscape:window-height="988"
inkscape:window-x="-8"
inkscape:window-y="-8"
showgrid="false"
inkscape:snap-bbox="false"
inkscape:snap-nodes="true"
inkscape:object-paths="false"
inkscape:object-nodes="true"
objecttolerance="10"
gridtolerance="10000"
guidetolerance="10000"
showborder="true"
inkscape:showpageshadow="true"
borderlayer="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-438.99979,0.6379836)">
<path
sodipodi:type="arc"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path2393"
sodipodi:cx="454"
sodipodi:cy="112.36218"
sodipodi:rx="87"
sodipodi:ry="56"
d="M 541,112.36218 A 87,56 0 1 1 367,112.36218 A 87,56 0 1 1 541,112.36218 z"
transform="matrix(-1.977323e-3,-1.724137,2.678569,-3.071905e-3,288.9275,932.4654)"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#000000;fill-opacity:1;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path1306"
sodipodi:cx="281.42856"
sodipodi:cy="270.93362"
sodipodi:rx="38.57143"
sodipodi:ry="44.285713"
d="M 319.99999,270.93362 A 38.57143,44.285713 0 1 1 242.85713,270.93362 A 38.57143,44.285713 0 1 1 319.99999,270.93362 z"
transform="matrix(0.972222,0,0,0.846774,264.7456,-151.7001)"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000" />
<text
xml:space="preserve"
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:url(#linearGradient2047);fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
x="511"
y="108.36218"
id="text1308"
sodipodi:linespacing="125%"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"><tspan
sodipodi:role="line"
id="tspan1312"
x="511"
y="108.36218"
style="fill:url(#linearGradient2047);fill-opacity:1">V</tspan></text>
<path
sodipodi:type="arc"
style="opacity:1;fill:#000000;fill-opacity:1;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path3517"
sodipodi:cx="454"
sodipodi:cy="112.36218"
sodipodi:rx="87"
sodipodi:ry="56"
d="M 541,112.36218 A 87,56 0 1 1 454,56.362183 L 454,112.36218 z"
transform="matrix(-1.977323e-3,-1.724137,2.678569,-3.071905e-3,288.9275,932.4654)"
sodipodi:start="0"
sodipodi:end="4.712389"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000" />
<text
xml:space="preserve"
style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
x="598"
y="105.36218"
id="text2055"
sodipodi:linespacing="125%"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"><tspan
sodipodi:role="line"
id="tspan2785"
x="598"
y="105.36218"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Arial Black">ideo</tspan></text>
<text
xml:space="preserve"
style="font-size:100px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
x="511"
y="243.36218"
id="text2051"
sodipodi:linespacing="125%"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"><tspan
sodipodi:role="line"
id="tspan2053"
x="511"
y="243.36218"
style="font-size:100px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:Arial Black">AG</tspan></text>
<text
xml:space="preserve"
style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:0.25098039;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black"
x="471"
y="108.36218"
id="text4979"
sodipodi:linespacing="125%"
inkscape:export-filename="C:\Eigene Dateien\Video AG\logo.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"><tspan
sodipodi:role="line"
id="tspan4981"
x="471"
y="108.36218">V</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -2,9 +2,10 @@ use super::cmd;
use crate::time::{format_time, Time}; use crate::time::{format_time, Time};
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf}; use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
use rational::Rational; use rational::Rational;
use std::process::Command; use std::{borrow::Cow, process::Command};
pub(crate) struct FfmpegInput { pub(crate) struct FfmpegInput {
pub(crate) concat: bool,
pub(crate) loop_input: bool, pub(crate) loop_input: bool,
pub(crate) fps: Option<Rational>, pub(crate) fps: Option<Rational>,
pub(crate) start: Option<Time>, pub(crate) start: Option<Time>,
@ -15,6 +16,7 @@ pub(crate) struct FfmpegInput {
impl FfmpegInput { impl FfmpegInput {
pub(crate) fn new(path: PathBuf) -> Self { pub(crate) fn new(path: PathBuf) -> Self {
Self { Self {
concat: false,
loop_input: false, loop_input: false,
fps: None, fps: None,
start: None, start: None,
@ -24,6 +26,9 @@ impl FfmpegInput {
} }
fn append_to_cmd(self, cmd: &mut Command) { fn append_to_cmd(self, cmd: &mut Command) {
if self.concat {
cmd.arg("-f").arg("concat").arg("-safe").arg("0");
}
if self.loop_input { if self.loop_input {
cmd.arg("-loop").arg("1"); 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 { pub(crate) struct Ffmpeg {
inputs: Vec<FfmpegInput>, inputs: Vec<FfmpegInput>,
filters: Vec<Filter>,
output: PathBuf output: PathBuf
} }
@ -49,6 +111,7 @@ impl Ffmpeg {
pub fn new(output: PathBuf) -> Self { pub fn new(output: PathBuf) -> Self {
Self { Self {
inputs: Vec::new(), inputs: Vec::new(),
filters: Vec::new(),
output output
} }
} }
@ -57,9 +120,13 @@ impl Ffmpeg {
let mut cmd = cmd(); let mut cmd = cmd();
cmd.arg("ffmpeg").arg("-hide_banner"); 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 // initialise a vaapi device if one exists
let vaapi_device: PathBuf = "/dev/dri/renderD128".into(); let vaapi_device: PathBuf = "/dev/dri/renderD128".into();
let vaapi = vaapi_device.exists(); let vaapi = venc && vaapi_device.exists();
if vaapi { if vaapi {
cmd.arg("-vaapi_device").arg(&vaapi_device); cmd.arg("-vaapi_device").arg(&vaapi_device);
} }
@ -72,6 +139,20 @@ impl Ffmpeg {
// always try to synchronise audio // always try to synchronise audio
cmd.arg("-async").arg("1"); 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!() unimplemented!()
} }
} }

View file

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