From 2fd358f3eda1c25992c2a1c2d0e1bef2506627cb Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Fri, 1 Nov 2024 12:28:52 -0400 Subject: [PATCH] feat(hls): add video quality preference (#306) --- src/settings.rs | 3 ++- src/utils.rs | 2 ++ static/playHLSVideo.js | 23 +++++++++++++++++++---- templates/base.html | 2 ++ templates/settings.html | 6 ++++++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index 617f308..4404912 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -21,7 +21,7 @@ struct SettingsTemplate { // CONSTANTS -const PREFS: [&str; 17] = [ +const PREFS: [&str; 18] = [ "theme", "front_page", "layout", @@ -39,6 +39,7 @@ const PREFS: [&str; 17] = [ "hide_awards", "hide_score", "disable_visit_reddit_confirmation", + "video_quality", ]; // FUNCTIONS diff --git a/src/utils.rs b/src/utils.rs index ab9e27b..170f53d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -612,6 +612,7 @@ pub struct Preferences { pub show_nsfw: String, pub blur_nsfw: String, pub hide_hls_notification: String, + pub video_quality: String, pub hide_sidebar_and_summary: String, pub use_hls: String, pub autoplay_videos: String, @@ -652,6 +653,7 @@ impl Preferences { blur_nsfw: setting(req, "blur_nsfw"), use_hls: setting(req, "use_hls"), hide_hls_notification: setting(req, "hide_hls_notification"), + video_quality: setting(req, "video_quality"), autoplay_videos: setting(req, "autoplay_videos"), fixed_navbar: setting_or_default(req, "fixed_navbar", "on".to_string()), disable_visit_reddit_confirmation: setting(req, "disable_visit_reddit_confirmation"), diff --git a/static/playHLSVideo.js b/static/playHLSVideo.js index 4f54e09..01f6809 100644 --- a/static/playHLSVideo.js +++ b/static/playHLSVideo.js @@ -1,5 +1,7 @@ // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 (function () { + const configElement = document.getElementById('video_quality'); + const qualitySetting = configElement.getAttribute('data-value'); if (Hls.isSupported()) { var videoSources = document.querySelectorAll("video source[type='application/vnd.apple.mpegurl']"); videoSources.forEach(function (source) { @@ -28,13 +30,26 @@ oldVideo.parentNode.replaceChild(newVideo, oldVideo); + function getIndexOfDefault(length) { + switch (qualitySetting) { + case 'best': + return length - 1; + case 'medium': + return Math.floor(length / 2); + case 'worst': + return 0; + default: + return length - 1; + } + } + function initializeHls() { newVideo.removeEventListener('play', initializeHls); var hls = new Hls({ autoStartLoad: false }); hls.loadSource(playlist); hls.attachMedia(newVideo); hls.on(Hls.Events.MANIFEST_PARSED, function () { - hls.loadLevel = hls.levels.length - 1; + hls.loadLevel = getIndexOfDefault(hls.levels.length); var availableLevels = hls.levels.map(function(level) { return { height: level.height, @@ -73,18 +88,18 @@ function addQualitySelector(videoElement, hlsInstance, availableLevels) { var qualitySelector = document.createElement('select'); qualitySelector.classList.add('quality-selector'); - var last = availableLevels.length - 1; + var defaultIndex = getIndexOfDefault(availableLevels.length); availableLevels.forEach(function (level, index) { var option = document.createElement('option'); option.value = index.toString(); var bitrate = (level.bitrate / 1_000).toFixed(0); option.text = level.height + 'p (' + bitrate + ' kbps)'; - if (index === last) { + if (index === defaultIndex) { option.selected = "selected"; } qualitySelector.appendChild(option); }); - qualitySelector.selectedIndex = availableLevels.length - 1; + qualitySelector.selectedIndex = defaultIndex; qualitySelector.addEventListener('change', function () { var selectedIndex = qualitySelector.selectedIndex; hlsInstance.nextLevel = selectedIndex; diff --git a/templates/base.html b/templates/base.html index 29122e0..a1c141b 100644 --- a/templates/base.html +++ b/templates/base.html @@ -27,6 +27,8 @@ + +
{% endblock %} + + +