feat(hls): add video quality preference (#306)

This commit is contained in:
Matthew Esposito 2024-11-01 12:28:52 -04:00 committed by GitHub
parent 5ef57812f8
commit 2fd358f3ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 31 additions and 5 deletions

View File

@ -21,7 +21,7 @@ struct SettingsTemplate {
// CONSTANTS // CONSTANTS
const PREFS: [&str; 17] = [ const PREFS: [&str; 18] = [
"theme", "theme",
"front_page", "front_page",
"layout", "layout",
@ -39,6 +39,7 @@ const PREFS: [&str; 17] = [
"hide_awards", "hide_awards",
"hide_score", "hide_score",
"disable_visit_reddit_confirmation", "disable_visit_reddit_confirmation",
"video_quality",
]; ];
// FUNCTIONS // FUNCTIONS

View File

@ -612,6 +612,7 @@ pub struct Preferences {
pub show_nsfw: String, pub show_nsfw: String,
pub blur_nsfw: String, pub blur_nsfw: String,
pub hide_hls_notification: String, pub hide_hls_notification: String,
pub video_quality: String,
pub hide_sidebar_and_summary: String, pub hide_sidebar_and_summary: String,
pub use_hls: String, pub use_hls: String,
pub autoplay_videos: String, pub autoplay_videos: String,
@ -652,6 +653,7 @@ impl Preferences {
blur_nsfw: setting(req, "blur_nsfw"), blur_nsfw: setting(req, "blur_nsfw"),
use_hls: setting(req, "use_hls"), use_hls: setting(req, "use_hls"),
hide_hls_notification: setting(req, "hide_hls_notification"), hide_hls_notification: setting(req, "hide_hls_notification"),
video_quality: setting(req, "video_quality"),
autoplay_videos: setting(req, "autoplay_videos"), autoplay_videos: setting(req, "autoplay_videos"),
fixed_navbar: setting_or_default(req, "fixed_navbar", "on".to_string()), fixed_navbar: setting_or_default(req, "fixed_navbar", "on".to_string()),
disable_visit_reddit_confirmation: setting(req, "disable_visit_reddit_confirmation"), disable_visit_reddit_confirmation: setting(req, "disable_visit_reddit_confirmation"),

View File

@ -1,5 +1,7 @@
// @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
(function () { (function () {
const configElement = document.getElementById('video_quality');
const qualitySetting = configElement.getAttribute('data-value');
if (Hls.isSupported()) { if (Hls.isSupported()) {
var videoSources = document.querySelectorAll("video source[type='application/vnd.apple.mpegurl']"); var videoSources = document.querySelectorAll("video source[type='application/vnd.apple.mpegurl']");
videoSources.forEach(function (source) { videoSources.forEach(function (source) {
@ -28,13 +30,26 @@
oldVideo.parentNode.replaceChild(newVideo, oldVideo); 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() { function initializeHls() {
newVideo.removeEventListener('play', initializeHls); newVideo.removeEventListener('play', initializeHls);
var hls = new Hls({ autoStartLoad: false }); var hls = new Hls({ autoStartLoad: false });
hls.loadSource(playlist); hls.loadSource(playlist);
hls.attachMedia(newVideo); hls.attachMedia(newVideo);
hls.on(Hls.Events.MANIFEST_PARSED, function () { 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) { var availableLevels = hls.levels.map(function(level) {
return { return {
height: level.height, height: level.height,
@ -73,18 +88,18 @@
function addQualitySelector(videoElement, hlsInstance, availableLevels) { function addQualitySelector(videoElement, hlsInstance, availableLevels) {
var qualitySelector = document.createElement('select'); var qualitySelector = document.createElement('select');
qualitySelector.classList.add('quality-selector'); qualitySelector.classList.add('quality-selector');
var last = availableLevels.length - 1; var defaultIndex = getIndexOfDefault(availableLevels.length);
availableLevels.forEach(function (level, index) { availableLevels.forEach(function (level, index) {
var option = document.createElement('option'); var option = document.createElement('option');
option.value = index.toString(); option.value = index.toString();
var bitrate = (level.bitrate / 1_000).toFixed(0); var bitrate = (level.bitrate / 1_000).toFixed(0);
option.text = level.height + 'p (' + bitrate + ' kbps)'; option.text = level.height + 'p (' + bitrate + ' kbps)';
if (index === last) { if (index === defaultIndex) {
option.selected = "selected"; option.selected = "selected";
} }
qualitySelector.appendChild(option); qualitySelector.appendChild(option);
}); });
qualitySelector.selectedIndex = availableLevels.length - 1; qualitySelector.selectedIndex = defaultIndex;
qualitySelector.addEventListener('change', function () { qualitySelector.addEventListener('change', function () {
var selectedIndex = qualitySelector.selectedIndex; var selectedIndex = qualitySelector.selectedIndex;
hlsInstance.nextLevel = selectedIndex; hlsInstance.nextLevel = selectedIndex;

View File

@ -27,6 +27,8 @@
<link rel="manifest" type="application/json" href="/manifest.json"> <link rel="manifest" type="application/json" href="/manifest.json">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico"> <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="stylesheet" type="text/css" href="/style.css?v={{ env!("CARGO_PKG_VERSION") }}"> <link rel="stylesheet" type="text/css" href="/style.css?v={{ env!("CARGO_PKG_VERSION") }}">
<!-- Video quality -->
<div id="video_quality" data-value="{{ prefs.video_quality }}"></div>
{% endblock %} {% endblock %}
</head> </head>
<body class=" <body class="

View File

@ -46,6 +46,12 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>Content</legend> <legend>Content</legend>
<div class="prefs-group">
<label for="video_quality">Video quality:</label>
<select name="video_quality" id="video_quality">
{% call utils::options(prefs.video_quality, ["best", "medium", "worst"], "best") %}
</select>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label> <label for="post_sort" title="Applies only to subreddit feeds">Default subreddit post sort:</label>
<select name="post_sort"> <select name="post_sort">