add assets; some cmd building
This commit is contained in:
parent
ffad525857
commit
c55906f70a
4 changed files with 307 additions and 3 deletions
8
assets/fastforward.svg
Normal file
8
assets/fastforward.svg
Normal 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
199
assets/logo.svg
Normal 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 |
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()?
|
||||
|
|
Loading…
Reference in a new issue