From 7d15cf00b4a32ccfbc60105af69f0ba3f3abf713 Mon Sep 17 00:00:00 2001 From: maximstewart Date: Sun, 28 Feb 2021 15:49:58 -0600 Subject: [PATCH] Fixing 1080p default playback --- README.md | 4 +- src/inject.js | 149 +++++++++++++++++++++++++++++++++++ src/manifest.json | 11 ++- src/scripts/betterYoutube.js | 20 ++--- 4 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 src/inject.js diff --git a/README.md b/README.md index 019bb9d..77319b7 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Better YouTube + works to improve the YouTube experience by providing quick acce * It shows volume level as you scroll. * It lets Unix, Linux, and MacOS systems have the ability to download the video using native app calls. -# Version: 1.5.6 -* 1080p playback defaulting... fix ...? +# Version: 1.5.7 +* Added injection script to default to 1080p playback # Download https://addons.mozilla.org/en-US/firefox/addon/better-youtube-plus/ diff --git a/src/inject.js b/src/inject.js new file mode 100644 index 0000000..f291f41 --- /dev/null +++ b/src/inject.js @@ -0,0 +1,149 @@ +'use strict'; + + +// ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto'] +const prefs = { + hd: true, + once: false, + higher: true, + quality: "hd1080", + log: false, + highFramerate: true +}; + + +const script = document.createElement('script'); +Object.assign(script.dataset, prefs); +script.textContent = ` + window.yttools = window.yttools || []; + + { + const isTypeSupported = MediaSource.isTypeSupported; + MediaSource.isTypeSupported = function(videoType) { + const prefs = resolutionChangeListener.prefs; + // Block all queries regarding high-framerate support. + if (prefs.highFramerate === 'false') { + const matches = videoType.match(/framerate=(\\d+)/); + if (matches && (matches[1] > 30)) { + return false; + } + } + return isTypeSupported(videoType); + } + } + + function resolutionChangeListener(e) { + const prefs = resolutionChangeListener.prefs; + const player = resolutionChangeListener.player; + const log = (...args) => prefs.log === 'true' && console.log('Better-Youtube-Plus: ', ...args); + + try { + if (e === 1 && player) { + const levels = player.getAvailableQualityLevels(); + if (levels.length === 0) { + return log("Returned empty quality levels..."); + } + + // ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto'] + const qualities = player.getAvailableQualityLevels(); + const q = player.getPlaybackQuality(); + if ((q.startsWith('h') && prefs.quality.startsWith('h')) && prefs.hd === 'true') { + console.log("Quality matches requested resolution..."); + return; + } + + const compare = (q1, q2) => { + if (q2 === 'auto') { + return false; + } + const i1 = qualities.indexOf(q1); + const i2 = qualities.indexOf(q2); + if (i1 === -1 || i2 === -1) { + return false; + } + return i1 - i2 <= 0; + }; + + if (prefs.higher === 'true' && compare(q, prefs.quality)) { + return log('Quality is higher than ' + prefs.quality + '... skipping quality change.'); + } + if (q === prefs.quality) { + return log('Selected quality is okay...'); + } + + const find = increase => { + if (prefs.quality === 'highest') { + return levels[0]; + } + else { + if (increase) { + prefs.quality = qualities[qualities.indexOf(prefs.quality) - 1] || levels[0]; + } + const index = levels.indexOf(prefs.quality); + if (index !== -1) { + return prefs.quality; + } + return find(true); + } + }; + + const nq = find(); + if (q === nq) { + return log('Requested quality is unavailable... skipping change.'); + } + player.setPlaybackQuality(nq); + try { + player.setPlaybackQualityRange(nq, nq); + } + catch (e) {} + if (prefs.once === 'true') { + player.removeEventListener('onStateChange', 'resolutionChangeListener'); + window.resolutionChangeListener = () => {}; + log("Removing Listener..."); + } + + log('Quality was ' + q + ' and now is set to ' + nq); + } + } + catch (e) { + log(e); + } + } + + resolutionChangeListener.prefs = document.currentScript.dataset; + window.yttools.push(e => { + resolutionChangeListener.player = e; + resolutionChangeListener(1); + e.addEventListener('onStateChange', resolutionChangeListener); + }); + + function onYouTubePlayerReady(player) { + if (yttools.resolved !== true) { + yttools.resolved = true; + yttools.forEach(c => { + try { + c(player); + } + catch (e) {} + }); + } + } + + + window.addEventListener('spfready', () => { + if (typeof window.ytplayer === 'object' && window.ytplayer.config && yttools.resolved !== true) { + window.ytplayer.config.args.jsapicallback = 'onYouTubePlayerReady'; + } + }); + + window.addEventListener('yt-navigate-finish', () => { + const player = document.querySelector('.html5-video-player'); + if (player && yttools.resolved !== true) { + yttools.resolved = true; + yttools.forEach(c => c(player)); + } + }); +`; + +document.documentElement.appendChild(script); +script.remove(); diff --git a/src/manifest.json b/src/manifest.json index 2f71fb4..808aa7b 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Better Youtube +", - "version": "1.5.6", + "version": "1.5.7", "description": "Enhancements for Youtube to have a better experience.", "applications": { @@ -13,9 +13,16 @@ "permissions": [ "nativeMessaging", "tabs", - "*://*.youtube.com/*" + "*://www.youtube.com/*" ], + "content_scripts": [{ + "matches": ["*://www.youtube.com/*"], + "js": ["inject.js"], + "run_at": "document_start", + "all_frames": true + }], + "icons": { "48": "icons/betterYoutube_48.png", "96": "icons/betterYoutube_96.png" diff --git a/src/scripts/betterYoutube.js b/src/scripts/betterYoutube.js index cb581ef..a4dde20 100644 --- a/src/scripts/betterYoutube.js +++ b/src/scripts/betterYoutube.js @@ -41,7 +41,7 @@ let ytThumbImgMenu, ytEnhancerMenu, ytEnhancerMenu2; // Menu systems let ytThumbnailBttn, ytLoopBttn, ytFloatBttn, ytDownloadBttn; // Menu Buttons let ytMaxDefaultImg, ytHqDefaultImg, ytAMaxDefaultImg, ytAHqDefaultImg; // Thumbnail images - let mainContentArea, playerWindow, containerOfPlyrWndow, video, player; // Youtube Player container + let mainContentArea, playerWindow, containerOfPlyrWndow, video; // Youtube Player container let videoTimeLength, videoTimeCurent, ytRangeStart, ytRangeEnd, slugInputTag, endlessPlayTag, ytVideoIntervalLoop, loopingInterval; @@ -153,6 +153,10 @@ slugInputTag.value = video.baseURI.slice(32, 32+11); ytRangeStart.value = "0:00"; + setTimeout(function () { + videoTimeLength = document.getElementsByClassName("ytp-time-duration")[0].innerText; + ytRangeEnd.value = videoTimeLength; + }, 2000); // Only setting these up if we need to load controls' info if (!controlsAreLoaded) { @@ -170,20 +174,6 @@ video.addEventListener("wheel", manageVolume); // Dragable window for floating video event setup dragVideo(poppedContainer); - - // I don't think this works... =[ - let resolutionStateChange = setInterval(function () { - player = document.getElementById("movie_player"); - if (video.readyState === 4 && player !== undefined) { - clearInterval(resolutionStateChange); - // ? Something like a meta information and signal object???? - // If 1080p not present, api plays the next lowest available resolution. - player.setPlaybackQualityRange("hd1080","hd1080"); - - videoTimeLength = document.getElementsByClassName("ytp-time-duration")[0].innerText; - ytRangeEnd.value = videoTimeLength; - } - }, 1000); } }