feat(hls): add video quality preference (#306)
This commit is contained in:
parent
5ef57812f8
commit
2fd358f3ed
@ -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
|
||||||
|
@ -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"),
|
||||||
|
@ -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;
|
||||||
|
@ -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="
|
||||||
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user