Skip to main content

jellytau_lib/download/
presets.rs

1//! The quality presets a video download can be asked for.
2//!
3//! One table, read by both the URL builder (which turns a preset into transcode
4//! parameters) and the size estimate (which turns the same numbers into an
5//! expected byte count). They were the same literals in two places before,
6//! which is how a bar can claim 40% of a file that is nearly done.
7
8/// Transcode caps for one named preset.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct DownloadPreset {
11    /// Video target, bits per second.
12    pub video_bit_rate: u64,
13    /// Longest edge the picture is scaled down to.
14    pub max_height: u32,
15    /// Audio target, bits per second.
16    pub audio_bit_rate: u64,
17}
18
19impl DownloadPreset {
20    /// Combined stream rate, bits per second.
21    pub fn total_bit_rate(&self) -> u64 {
22        self.video_bit_rate + self.audio_bit_rate
23    }
24}
25
26/// The preset a quality name denotes; `None` for `original` and anything
27/// unrecognised, both of which mean "do not cap the picture".
28///
29/// TRACES: UR-071 | DR-123, DR-290
30pub fn download_preset(quality: &str) -> Option<DownloadPreset> {
31    match quality {
32        "high" => Some(DownloadPreset {
33            video_bit_rate: 8_000_000,
34            max_height: 1080,
35            audio_bit_rate: 384_000,
36        }),
37        "medium" => Some(DownloadPreset {
38            video_bit_rate: 4_000_000,
39            max_height: 720,
40            audio_bit_rate: 256_000,
41        }),
42        "low" => Some(DownloadPreset {
43            video_bit_rate: 1_500_000,
44            max_height: 480,
45            audio_bit_rate: 128_000,
46        }),
47        _ => None,
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_presets_are_ordered_and_original_has_none() {
57        let high = download_preset("high").unwrap();
58        let medium = download_preset("medium").unwrap();
59        let low = download_preset("low").unwrap();
60        assert!(high.total_bit_rate() > medium.total_bit_rate());
61        assert!(medium.total_bit_rate() > low.total_bit_rate());
62        assert!(high.max_height > medium.max_height && medium.max_height > low.max_height);
63        assert_eq!(download_preset("original"), None);
64        assert_eq!(download_preset("nonsense"), None);
65    }
66}