fix warnings
This commit is contained in:
parent
fad0d1ec6c
commit
27e986d53b
5 changed files with 33 additions and 98 deletions
|
@ -1,5 +1,5 @@
|
||||||
#![allow(clippy::manual_range_contains)]
|
#![allow(clippy::manual_range_contains)]
|
||||||
#![warn(rust_2018_idioms)]
|
#![warn(clippy::unreadable_literal, rust_2018_idioms)]
|
||||||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||||
|
|
||||||
mod iotro;
|
mod iotro;
|
||||||
|
@ -281,7 +281,9 @@ fn main() {
|
||||||
|
|
||||||
// render the video
|
// render the video
|
||||||
let mut videos = Vec::new();
|
let mut videos = Vec::new();
|
||||||
videos.push(if !project.progress.rendered {
|
videos.push(if project.progress.rendered {
|
||||||
|
renderer.video_mp4(&project)
|
||||||
|
} else {
|
||||||
let video = renderer.render(&mut project).unwrap();
|
let video = renderer.render(&mut project).unwrap();
|
||||||
project.progress.rendered = true;
|
project.progress.rendered = true;
|
||||||
|
|
||||||
|
@ -289,8 +291,6 @@ 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();
|
||||||
|
|
||||||
video
|
video
|
||||||
} else {
|
|
||||||
renderer.video_mp4(&project)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// rescale the video
|
// rescale the video
|
||||||
|
|
|
@ -227,12 +227,13 @@ impl Ffmpeg {
|
||||||
FfmpegFilter::Filters { filters, output } => {
|
FfmpegFilter::Filters { filters, output } => {
|
||||||
let mut complex = String::new();
|
let mut complex = String::new();
|
||||||
for filter in filters {
|
for filter in filters {
|
||||||
filter.append_to_complex_filter(&mut complex, &mut self.filter_idx);
|
filter
|
||||||
|
.append_to_complex_filter(&mut complex, &mut self.filter_idx)?;
|
||||||
}
|
}
|
||||||
if vaapi {
|
if vaapi {
|
||||||
write!(complex, "{}format=nv12,hwupload[v]", channel('v', &output));
|
write!(complex, "{}format=nv12,hwupload[v]", channel('v', &output))?;
|
||||||
} else {
|
} else {
|
||||||
write!(complex, "{}null[v]", channel('v', &output));
|
write!(complex, "{}null[v]", channel('v', &output))?;
|
||||||
}
|
}
|
||||||
cmd.arg("-filter_complex").arg(complex);
|
cmd.arg("-filter_complex").arg(complex);
|
||||||
cmd.arg("-map").arg("[v]");
|
cmd.arg("-map").arg("[v]");
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
use crate::time::{format_time, Time};
|
use crate::time::Time;
|
||||||
use std::{borrow::Cow, collections::VecDeque, fmt::Write as _};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::VecDeque,
|
||||||
|
fmt::{self, Write as _}
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) enum Filter {
|
pub(crate) enum Filter {
|
||||||
/// Trim audio and video alike
|
|
||||||
Trim {
|
|
||||||
input: Cow<'static, str>,
|
|
||||||
start: Option<Time>,
|
|
||||||
duration: Option<Time>,
|
|
||||||
output: Cow<'static, str>
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Apply an alpha channel on the video. No audio.
|
/// Apply an alpha channel on the video. No audio.
|
||||||
Alpha {
|
Alpha {
|
||||||
input: Cow<'static, str>,
|
input: Cow<'static, str>,
|
||||||
|
@ -57,63 +53,12 @@ pub(crate) enum Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Filter {
|
impl Filter {
|
||||||
pub(crate) fn is_video_filter(&self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Self::Trim { .. }
|
|
||||||
| Self::Alpha { .. }
|
|
||||||
| Self::Concat { .. }
|
|
||||||
| Self::Fade { .. }
|
|
||||||
| Self::Overlay { .. }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_audio_filter(&self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Self::Trim { .. }
|
|
||||||
| Self::Concat { .. }
|
|
||||||
| Self::Fade { .. }
|
|
||||||
| Self::GenerateSilence { .. }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn append_to_complex_filter(
|
pub(crate) fn append_to_complex_filter(
|
||||||
&self,
|
&self,
|
||||||
complex: &mut String,
|
complex: &mut String,
|
||||||
filter_idx: &mut usize
|
filter_idx: &mut usize
|
||||||
) {
|
) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Trim {
|
|
||||||
input,
|
|
||||||
start,
|
|
||||||
duration,
|
|
||||||
output
|
|
||||||
} => {
|
|
||||||
let mut args = String::new();
|
|
||||||
if let Some(start) = start {
|
|
||||||
write!(args, "start={start}");
|
|
||||||
}
|
|
||||||
if let Some(duration) = duration {
|
|
||||||
if !args.is_empty() {
|
|
||||||
args += ":";
|
|
||||||
}
|
|
||||||
write!(args, "duration={duration}");
|
|
||||||
}
|
|
||||||
writeln!(
|
|
||||||
complex,
|
|
||||||
"{}trim={args},setpts=PTS-STARTPTS{};",
|
|
||||||
channel('v', input),
|
|
||||||
channel('v', output)
|
|
||||||
);
|
|
||||||
writeln!(
|
|
||||||
complex,
|
|
||||||
"{}atrim={args},asetpts=PTS-STARTPTS{};",
|
|
||||||
channel('a', input),
|
|
||||||
channel('a', output)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
Self::Alpha {
|
Self::Alpha {
|
||||||
input,
|
input,
|
||||||
alpha,
|
alpha,
|
||||||
|
@ -124,7 +69,7 @@ impl Filter {
|
||||||
"{}format=yuva444p,colorchannelmixer=aa={alpha}{};",
|
"{}format=yuva444p,colorchannelmixer=aa={alpha}{};",
|
||||||
channel('v', input),
|
channel('v', input),
|
||||||
channel('v', output)
|
channel('v', output)
|
||||||
);
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::Overlay {
|
Self::Overlay {
|
||||||
|
@ -140,18 +85,18 @@ impl Filter {
|
||||||
channel('v', video_input),
|
channel('v', video_input),
|
||||||
channel('v', overlay_input),
|
channel('v', overlay_input),
|
||||||
channel('v', output)
|
channel('v', output)
|
||||||
);
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
"{}anull{};",
|
"{}anull{};",
|
||||||
channel('a', video_input),
|
channel('a', video_input),
|
||||||
channel('a', output)
|
channel('a', output)
|
||||||
);
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::Concat { inputs, output } => {
|
Self::Concat { inputs, output } => {
|
||||||
for i in inputs {
|
for i in inputs {
|
||||||
write!(complex, "{}{}", channel('v', i), channel('a', i));
|
write!(complex, "{}{}", channel('v', i), channel('a', i))?;
|
||||||
}
|
}
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
|
@ -159,7 +104,7 @@ impl Filter {
|
||||||
inputs.len(),
|
inputs.len(),
|
||||||
channel('v', output),
|
channel('v', output),
|
||||||
channel('a', output)
|
channel('a', output)
|
||||||
);
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::Fade {
|
Self::Fade {
|
||||||
|
@ -175,13 +120,13 @@ impl Filter {
|
||||||
"{}fade={args}{};",
|
"{}fade={args}{};",
|
||||||
channel('v', input),
|
channel('v', input),
|
||||||
channel('v', output)
|
channel('v', output)
|
||||||
);
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
"{}afade=t={args}{};",
|
"{}afade=t={args}{};",
|
||||||
channel('a', input),
|
channel('a', input),
|
||||||
channel('a', output)
|
channel('a', output)
|
||||||
);
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::GenerateSilence { video, output } => {
|
Self::GenerateSilence { video, output } => {
|
||||||
|
@ -190,12 +135,12 @@ impl Filter {
|
||||||
"{}null{};",
|
"{}null{};",
|
||||||
channel('v', video),
|
channel('v', video),
|
||||||
channel('v', output)
|
channel('v', output)
|
||||||
);
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
"aevalsrc=0:s=48000,pan=stereo|c0=c0|c1=c0{};",
|
"aevalsrc=0:s=48000,pan=stereo|c0=c0|c1=c0{};",
|
||||||
channel('a', output)
|
channel('a', output)
|
||||||
);
|
)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::FastForward {
|
Self::FastForward {
|
||||||
|
@ -209,29 +154,29 @@ impl Filter {
|
||||||
complex,
|
complex,
|
||||||
"{}setpts=PTS/{multiplier}{vff};",
|
"{}setpts=PTS/{multiplier}{vff};",
|
||||||
channel('v', input)
|
channel('v', input)
|
||||||
);
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
"{}atempo={multiplier}{};",
|
"{}atempo={multiplier}{};",
|
||||||
channel('a', input),
|
channel('a', input),
|
||||||
channel('a', output)
|
channel('a', output)
|
||||||
);
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
complex,
|
complex,
|
||||||
"{vff}{}overlay=x=main_w/2-overlay_w/2:y=main_h/2-overlay_h/2{};",
|
"{vff}{}overlay=x=main_w/2-overlay_w/2:y=main_h/2-overlay_h/2{};",
|
||||||
channel('v', ffinput),
|
channel('v', ffinput),
|
||||||
channel('v', output)
|
channel('v', output)
|
||||||
);
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a newline after every filter to ease debugging
|
// add a newline after every filter to ease debugging
|
||||||
writeln!(complex);
|
writeln!(complex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn channel(channel: char, id: &str) -> String {
|
pub(super) fn channel(channel: char, id: &str) -> String {
|
||||||
if id.chars().any(|ch| !ch.is_digit(10)) {
|
if id.chars().any(|ch| !ch.is_ascii_digit()) {
|
||||||
format!("[{channel}_{id}]")
|
format!("[{channel}_{id}]")
|
||||||
} else {
|
} else {
|
||||||
format!("[{id}:{channel}]")
|
format!("[{id}:{channel}]")
|
||||||
|
@ -242,11 +187,3 @@ fn next_tmp(filter_idx: &mut usize) -> String {
|
||||||
*filter_idx += 1;
|
*filter_idx += 1;
|
||||||
format!("[tmp{filter_idx}]")
|
format!("[tmp{filter_idx}]")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_tmp_3(filter_idx: &mut usize) -> [String; 3] {
|
|
||||||
[
|
|
||||||
next_tmp(filter_idx),
|
|
||||||
next_tmp(filter_idx),
|
|
||||||
next_tmp(filter_idx)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(warnings)]
|
|
||||||
|
|
||||||
pub mod ffmpeg;
|
pub mod ffmpeg;
|
||||||
mod filter;
|
mod filter;
|
||||||
|
|
||||||
|
@ -12,7 +10,6 @@ use crate::{
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
|
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
|
||||||
use rational::Rational;
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
|
@ -189,7 +186,7 @@ impl<'a> Renderer<'a> {
|
||||||
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 {
|
||||||
writeln!(file, "file '{}'", self.directory.join(filename).to_string());
|
writeln!(file, "file '{}'", self.directory.join(filename))?;
|
||||||
}
|
}
|
||||||
drop(file);
|
drop(file);
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ pub fn parse_time(s: &str) -> anyhow::Result<Time> {
|
||||||
}
|
}
|
||||||
// the 4th split is subseconds, converting to micros
|
// the 4th split is subseconds, converting to micros
|
||||||
if i == 3 {
|
if i == 3 {
|
||||||
micros = digits.parse::<u32>()? * 1000000 / 60;
|
micros = digits.parse::<u32>()? * 1_000_000 / 60;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// add to seconds and potentially micros
|
// add to seconds and potentially micros
|
||||||
|
@ -230,7 +230,7 @@ mod tests {
|
||||||
fn test_time_subsecs() {
|
fn test_time_subsecs() {
|
||||||
test_time_parse_only("1:02:03:30", Time {
|
test_time_parse_only("1:02:03:30", Time {
|
||||||
seconds: 3723,
|
seconds: 3723,
|
||||||
micros: 500000
|
micros: 500_000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ mod tests {
|
||||||
fn test_time_micros() {
|
fn test_time_micros() {
|
||||||
test_time("1:02:03.5", Time {
|
test_time("1:02:03.5", Time {
|
||||||
seconds: 3723,
|
seconds: 3723,
|
||||||
micros: 500000
|
micros: 500_000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue