move project structs into their own mod
This commit is contained in:
parent
b6bd1be12e
commit
1dfe835587
2 changed files with 7 additions and 164 deletions
167
src/main.rs
167
src/main.rs
|
@ -3,30 +3,26 @@
|
||||||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||||
|
|
||||||
mod iotro;
|
mod iotro;
|
||||||
|
mod project;
|
||||||
mod question;
|
mod question;
|
||||||
mod render;
|
mod render;
|
||||||
mod time;
|
mod time;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
iotro::Language,
|
iotro::Language,
|
||||||
question::Question,
|
project::{Project, ProjectLecture, ProjectSource, Resolution},
|
||||||
render::{ffmpeg::FfmpegOutputFormat, Renderer},
|
render::Renderer,
|
||||||
time::{parse_date, parse_time, Date, Time}
|
time::{parse_date, parse_time, Time}
|
||||||
};
|
};
|
||||||
use camino::Utf8PathBuf as PathBuf;
|
use camino::Utf8PathBuf as PathBuf;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console::style;
|
use console::style;
|
||||||
use rational::Rational;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_with::{serde_as, DisplayFromStr};
|
|
||||||
#[cfg(feature = "mem_limit")]
|
#[cfg(feature = "mem_limit")]
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeSet,
|
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
fs,
|
fs,
|
||||||
io::{self, BufRead as _, Write},
|
io::{self, BufRead as _, Write}
|
||||||
str::FromStr
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "mem_limit")]
|
#[cfg(feature = "mem_limit")]
|
||||||
|
@ -73,159 +69,6 @@ struct Args {
|
||||||
stereo: bool
|
stereo: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! resolutions {
|
|
||||||
($($res:ident: $width:literal x $height:literal at $bitrate:literal in $format:ident),+) => {
|
|
||||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
|
||||||
enum Resolution {
|
|
||||||
$(
|
|
||||||
#[doc = concat!(stringify!($width), "x", stringify!($height))]
|
|
||||||
$res
|
|
||||||
),+
|
|
||||||
}
|
|
||||||
|
|
||||||
const NUM_RESOLUTIONS: usize = {
|
|
||||||
let mut num = 0;
|
|
||||||
$(num += 1; stringify!($res);)+
|
|
||||||
num
|
|
||||||
};
|
|
||||||
|
|
||||||
impl Resolution {
|
|
||||||
fn values() -> [Self; NUM_RESOLUTIONS] {
|
|
||||||
[$(Self::$res),+]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn width(self) -> usize {
|
|
||||||
match self {
|
|
||||||
$(Self::$res => $width),+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn height(self) -> usize {
|
|
||||||
match self {
|
|
||||||
$(Self::$res => $height),+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bitrate(self) -> u64 {
|
|
||||||
match self {
|
|
||||||
$(Self::$res => $bitrate),+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format(self) -> FfmpegOutputFormat {
|
|
||||||
match self {
|
|
||||||
$(Self::$res => FfmpegOutputFormat::$format),+
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Resolution {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> anyhow::Result<Self> {
|
|
||||||
Ok(match s {
|
|
||||||
$(concat!(stringify!($height), "p") => Self::$res,)+
|
|
||||||
_ => anyhow::bail!("Unknown Resolution: {s:?}")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolutions! {
|
|
||||||
nHD: 640 x 360 at 500_000 in AvcAac,
|
|
||||||
HD: 1280 x 720 at 1_000_000 in AvcAac,
|
|
||||||
FullHD: 1920 x 1080 at 750_000 in Av1Opus,
|
|
||||||
WQHD: 2560 x 1440 at 1_000_000 in Av1Opus,
|
|
||||||
// TODO qsx muss mal sagen wieviel bitrate für 4k
|
|
||||||
UHD: 3840 x 2160 at 2_000_000 in Av1Opus
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
struct Project {
|
|
||||||
lecture: ProjectLecture,
|
|
||||||
source: ProjectSource,
|
|
||||||
progress: ProjectProgress
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_as]
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
struct ProjectLecture {
|
|
||||||
course: String,
|
|
||||||
label: String,
|
|
||||||
docent: String,
|
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
date: Date,
|
|
||||||
#[serde(default = "Default::default")]
|
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
lang: Language<'static>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_as]
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
struct ProjectSource {
|
|
||||||
files: Vec<String>,
|
|
||||||
stereo: bool,
|
|
||||||
|
|
||||||
#[serde_as(as = "Option<DisplayFromStr>")]
|
|
||||||
start: Option<Time>,
|
|
||||||
#[serde_as(as = "Option<DisplayFromStr>")]
|
|
||||||
end: Option<Time>,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde_as(as = "Vec<(DisplayFromStr, DisplayFromStr)>")]
|
|
||||||
fast: Vec<(Time, Time)>,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde_as(as = "Vec<(DisplayFromStr, DisplayFromStr, _)>")]
|
|
||||||
questions: Vec<(Time, Time, String)>,
|
|
||||||
|
|
||||||
metadata: Option<ProjectSourceMetadata>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[serde_as]
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
struct ProjectSourceMetadata {
|
|
||||||
/// The duration of the source video.
|
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
source_duration: Time,
|
|
||||||
/// The FPS of the source video.
|
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
source_fps: Rational,
|
|
||||||
/// The time base of the source video.
|
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
source_tbn: Rational,
|
|
||||||
/// The resolution of the source video.
|
|
||||||
source_res: Resolution,
|
|
||||||
/// The sample rate of the source audio.
|
|
||||||
source_sample_rate: u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Deserialize, Serialize)]
|
|
||||||
struct ProjectProgress {
|
|
||||||
#[serde(default)]
|
|
||||||
preprocessed: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
asked_start_end: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
asked_fast: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
asked_questions: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
rendered_assets: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
rendered: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
transcoded: BTreeSet<Resolution>
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ask(question: impl Display) -> String {
|
fn ask(question: impl Display) -> String {
|
||||||
let mut stdout = io::stdout().lock();
|
let mut stdout = io::stdout().lock();
|
||||||
let mut stdin = io::stdin().lock();
|
let mut stdin = io::stdin().lock();
|
||||||
|
|
|
@ -7,10 +7,10 @@ use self::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
iotro::{intro, outro},
|
iotro::{intro, outro},
|
||||||
|
project::{Project, ProjectLecture, ProjectSourceMetadata, Resolution},
|
||||||
question::Question,
|
question::Question,
|
||||||
render::ffmpeg::{Ffmpeg, FfmpegInput},
|
render::ffmpeg::{Ffmpeg, FfmpegInput},
|
||||||
time::{format_date, format_time, Time},
|
time::{format_date, format_time, Time}
|
||||||
Project, ProjectLecture, ProjectSourceMetadata, Resolution
|
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
|
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
|
||||||
|
|
Loading…
Reference in a new issue