diff --git a/src/iotro.rs b/src/iotro.rs
index cdbd1b28ad707fbedd313f3ceaa12a01be343162..e37045ea6d24333300b1078cec70e1a73354d625 100644
--- a/src/iotro.rs
+++ b/src/iotro.rs
@@ -191,8 +191,8 @@ impl Iotro {
 
 	fn finish(self) -> Graphic {
 		let mut svg = Graphic::new();
-		svg.set_width(self.res.width);
-		svg.set_height(self.res.height);
+		svg.set_width(self.res.width());
+		svg.set_height(self.res.height());
 		svg.set_view_box("0 0 1920 1080");
 		svg.push(
 			Rect::new()
diff --git a/src/project.rs b/src/project.rs
index 36113178480edaf3be8076560c70abc586fe7625..93d7a45b0d57730f9698348e2fe035862365e0b7 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -16,32 +16,41 @@ use std::{
 };
 
 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
-pub struct Resolution {
-	pub width: u32,
-	pub height: u32
-}
+pub struct Resolution(u32, u32);
 
 impl Resolution {
+	pub fn new(width: u32, height: u32) -> Self {
+		Self(width, height)
+	}
+
+	pub fn width(self) -> u32 {
+		self.0
+	}
+
+	pub fn height(self) -> u32 {
+		self.1
+	}
+
 	pub(crate) fn bitrate(self) -> u64 {
 		// 640 * 360: 500k
-		if self.width <= 640 {
+		if self.width() <= 640 {
 			500_000
 		}
 		// 1280 * 720: 1M
-		else if self.width <= 1280 {
+		else if self.width() <= 1280 {
 			1_000_000
 		}
 		// 1920 * 1080: 2M
-		else if self.width <= 1920 {
+		else if self.width() <= 1920 {
 			2_000_000
 		}
 		// 2560 * 1440: 3M
-		else if self.width <= 2560 {
+		else if self.width() <= 2560 {
 			3_000_000
 		}
 		// 3840 * 2160: 4M
 		// TODO die bitrate von 4M ist absolut an den haaren herbeigezogen
-		else if self.width <= 3840 {
+		else if self.width() <= 3840 {
 			4_000_000
 		}
 		// we'll cap everything else at 5M for no apparent reason
@@ -51,7 +60,7 @@ impl Resolution {
 	}
 
 	pub(crate) fn default_codec(self) -> FfmpegOutputFormat {
-		if self.width > 1920 {
+		if self.width() > 1920 {
 			FfmpegOutputFormat::Av1Opus
 		} else {
 			FfmpegOutputFormat::AvcAac
@@ -59,32 +68,17 @@ impl Resolution {
 	}
 
 	pub const STANDARD_RESOLUTIONS: [Self; 5] = [
-		Self {
-			width: 640,
-			height: 360
-		},
-		Self {
-			width: 1280,
-			height: 720
-		},
-		Self {
-			width: 1920,
-			height: 1080
-		},
-		Self {
-			width: 2560,
-			height: 1440
-		},
-		Self {
-			width: 3840,
-			height: 2160
-		}
+		Self(640, 360),
+		Self(1280, 720),
+		Self(1920, 1080),
+		Self(2560, 1440),
+		Self(3840, 2160)
 	];
 }
 
 impl Display for Resolution {
 	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-		write!(f, "{}p", self.height)
+		write!(f, "{}p", self.height())
 	}
 }
 
@@ -93,34 +87,13 @@ impl FromStr for Resolution {
 
 	fn from_str(s: &str) -> anyhow::Result<Self> {
 		Ok(match s.to_lowercase().as_str() {
-			"360p" | "nhd" => Self {
-				width: 640,
-				height: 360
-			},
-			"540p" | "qhd" => Self {
-				width: 960,
-				height: 540
-			},
-			"720p" | "hd" => Self {
-				width: 1280,
-				height: 720
-			},
-			"900p" | "hd+" => Self {
-				width: 1600,
-				height: 900
-			},
-			"1080p" | "fhd" | "fullhd" => Self {
-				width: 1920,
-				height: 1080
-			},
-			"1440p" | "wqhd" => Self {
-				width: 2560,
-				height: 1440
-			},
-			"2160p" | "4k" | "uhd" => Self {
-				width: 3840,
-				height: 2160
-			},
+			"360p" | "nhd" => Self(640, 360),
+			"540p" | "qhd" => Self(960, 540),
+			"720p" | "hd" => Self(1280, 720),
+			"900p" | "hd+" => Self(1600, 900),
+			"1080p" | "fhd" | "fullhd" => Self(1920, 1080),
+			"1440p" | "wqhd" => Self(2560, 1440),
+			"2160p" | "4k" | "uhd" => Self(3840, 2160),
 			_ => anyhow::bail!("Unknown Resolution: {s:?}")
 		})
 	}
@@ -128,7 +101,7 @@ impl FromStr for Resolution {
 
 impl Ord for Resolution {
 	fn cmp(&self, other: &Self) -> cmp::Ordering {
-		(self.width * self.height).cmp(&(other.width * other.height))
+		(self.0 * self.1).cmp(&(other.0 * other.1))
 	}
 }
 
@@ -146,7 +119,7 @@ impl PartialEq for Resolution {
 	}
 }
 
-#[derive(Deserialize, Serialize)]
+#[derive(Debug, Deserialize, Serialize)]
 pub struct Project {
 	pub lecture: ProjectLecture,
 	pub source: ProjectSource,
@@ -154,7 +127,7 @@ pub struct Project {
 }
 
 #[serde_as]
-#[derive(Deserialize, Serialize)]
+#[derive(Debug, Deserialize, Serialize)]
 pub struct ProjectLecture {
 	pub course: String,
 	pub label: String,
@@ -167,7 +140,7 @@ pub struct ProjectLecture {
 }
 
 #[serde_as]
-#[derive(Deserialize, Serialize)]
+#[derive(Debug, Deserialize, Serialize)]
 pub struct ProjectSource {
 	pub files: Vec<String>,
 	pub stereo: bool,
@@ -189,7 +162,7 @@ pub struct ProjectSource {
 }
 
 #[serde_as]
-#[derive(Deserialize, Serialize)]
+#[derive(Debug, Deserialize, Serialize)]
 pub struct ProjectSourceMetadata {
 	/// The duration of the source video.
 	#[serde_as(as = "DisplayFromStr")]
@@ -207,7 +180,7 @@ pub struct ProjectSourceMetadata {
 }
 
 #[serde_as]
-#[derive(Default, Deserialize, Serialize)]
+#[derive(Debug, Default, Deserialize, Serialize)]
 pub struct ProjectProgress {
 	#[serde(default)]
 	pub preprocessed: bool,
diff --git a/src/question.rs b/src/question.rs
index 0f61a1c96eb55134d5db277863f9e99bf85c39f0..6bf0da635c0568b289d816470fd502e5321d4a43 100644
--- a/src/question.rs
+++ b/src/question.rs
@@ -131,8 +131,8 @@ impl Question {
 
 	pub(crate) fn finish(self) -> Graphic {
 		let mut svg = Graphic::new();
-		svg.set_width(self.res.width);
-		svg.set_height(self.res.height);
+		svg.set_width(self.res.width());
+		svg.set_height(self.res.height());
 		svg.set_view_box("0 0 1920 1080");
 		svg.push(self.g);
 		svg
diff --git a/src/render/ffmpeg.rs b/src/render/ffmpeg.rs
index af4109561ea465c96d44ed2c5da6f41334afa38b..07bca84d43fc739d9c1d3be1bc913dfec4f5cbb8 100644
--- a/src/render/ffmpeg.rs
+++ b/src/render/ffmpeg.rs
@@ -359,9 +359,9 @@ impl Ffmpeg {
 			},
 			FfmpegFilter::Rescale(res) => {
 				cmd.arg("-vf").arg(if vaapi {
-					format!("scale_vaapi=w={}:h={}", res.width, res.height)
+					format!("scale_vaapi=w={}:h={}", res.width(), res.height())
 				} else {
-					format!("scale=w={}:h={}", res.width, res.height)
+					format!("scale=w={}:h={}", res.width(), res.height())
 				});
 			}
 		}
diff --git a/src/render/mod.rs b/src/render/mod.rs
index 1845862606cb39af8b83732b60c5efee2f242c26..332bea1dce5f71c57318ee6f0c3856532cc4fdb7 100644
--- a/src/render/mod.rs
+++ b/src/render/mod.rs
@@ -264,7 +264,7 @@ impl<'a> Renderer<'a> {
 
 		let width = ffprobe_video("stream=width", &recording_mkv)?.parse()?;
 		let height = ffprobe_video("stream=height", &recording_mkv)?.parse()?;
-		let source_res = Resolution { width, height };
+		let source_res = Resolution::new(width, height);
 		project.source.metadata = Some(ProjectSourceMetadata {
 			source_duration: ffprobe_video("format=duration", &recording_mkv)?.parse()?,
 			source_fps: ffprobe_video("stream=r_frame_rate", &recording_mkv)?.parse()?,
@@ -316,7 +316,7 @@ impl<'a> Renderer<'a> {
 			include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/logo.svg"))
 		)?;
 		let logo_png = self.target.join("logo.png");
-		let logo_size = LOGO_SIZE * metadata.source_res.width / 1920;
+		let logo_size = LOGO_SIZE * metadata.source_res.width() / 1920;
 		svg2png(&logo_svg, &logo_png, logo_size, logo_size)?;
 
 		// copy fastforward then render to png
@@ -329,7 +329,7 @@ impl<'a> Renderer<'a> {
 			))
 		)?;
 		let fastforward_png = self.target.join("fastforward.png");
-		let ff_logo_size = FF_LOGO_SIZE * metadata.source_res.width / 1920;
+		let ff_logo_size = FF_LOGO_SIZE * metadata.source_res.width() / 1920;
 		svg2png(
 			&fastforward_svg,
 			&fastforward_png,
@@ -349,8 +349,8 @@ impl<'a> Renderer<'a> {
 			svg2png(
 				&q_svg,
 				&q_png,
-				metadata.source_res.width,
-				metadata.source_res.height
+				metadata.source_res.width(),
+				metadata.source_res.height()
 			)?;
 		}
 
@@ -365,7 +365,7 @@ impl<'a> Renderer<'a> {
 			FfmpegOutputFormat::AvcAac => "mp4"
 		};
 		self.target
-			.join(format!("{}-{}p.{extension}", self.slug, res.height))
+			.join(format!("{}-{}p.{extension}", self.slug, res.height()))
 	}
 
 	/// Get the video file directly outputed to further transcode.
@@ -622,8 +622,8 @@ impl<'a> Renderer<'a> {
 			output: logoalpha.into()
 		});
 		let overlay = "overlay";
-		let overlay_off_x = 130 * source_res.width / 3840;
-		let overlay_off_y = 65 * source_res.height / 2160;
+		let overlay_off_x = 130 * source_res.width() / 3840;
+		let overlay_off_y = 65 * source_res.height() / 2160;
 		ffmpeg.add_filter(Filter::Overlay {
 			video_input: concat.into(),
 			overlay_input: logoalpha.into(),
@@ -652,7 +652,7 @@ impl<'a> Renderer<'a> {
 		println!(
 			" {} {}",
 			style("==>").bold().cyan(),
-			style(format!("Rescaling to {}p", res.height)).bold()
+			style(format!("Rescaling to {}p", res.height())).bold()
 		);
 
 		let mut ffmpeg = Ffmpeg::new(FfmpegOutput {