This repository has been archived by the owner on Jul 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 218
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
automatically upgrade default YouTube video playback quality to HD 14…
…40p (fixes issue #1051); hide `Full screen is unavailable` message (fixes issue #1056) - or via `vq=`/`query=` query-string parameter in URLs for youtube.com and youtube-nocookie.com
- Loading branch information
Showing
4 changed files
with
179 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 4 additions & 3 deletions
7
app/src/main/assets/web_extensions/youtube_webcompat/main.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* To hide harmless warning about 360° video playback. */ | ||
div.alert-with-button-renderer, | ||
ytm-alert-with-button-renderer { | ||
/* To hide harmless warnings. */ | ||
.alert-with-button-renderer, .ytm-alert-with-button-renderer, ytm-alert-with-button-renderer, | ||
.ytp-ad-module, ytp-ad-module | ||
.ytp-generic-popup, ytp-generic-popup { | ||
display: none; | ||
} |
179 changes: 167 additions & 12 deletions
179
app/src/main/assets/web_extensions/youtube_webcompat/main.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,174 @@ | ||
(function () { | ||
// If missing, inject a `<meta name="viewport">` tag to trigger YouTube's mobile layout. | ||
const viewport = document.head.querySelector('meta[name="viewport"]'); | ||
if (!viewport) { | ||
viewport = document.createElement('meta'); | ||
viewport.name = 'viewport'; | ||
viewport.content = 'width=user-width, initial-scale=1'; | ||
document.head.appendChild(viewport); | ||
window.addEventListener('load', () => { | ||
let viewport = document.head.querySelector('meta[name="viewport"]'); | ||
if (!viewport) { | ||
viewport = document.createElement('meta'); | ||
viewport.name = 'viewport'; | ||
viewport.content = 'width=device-width, initial-scale=1'; | ||
document.head.appendChild(viewport); | ||
} | ||
}); | ||
|
||
const LOGTAG = '[firefoxreality:webcompat]' | ||
const qs = new URLSearchParams(window.location.search); | ||
let retryTimeout = null; | ||
|
||
function getTruthyQS (key) { | ||
if (!qs || !qs.has(key)) { | ||
return false; | ||
} | ||
const valueLower = (qs.get('key') || '').trim().toLowerCase(); | ||
return valueLower === '' || valueLower === '1' || valueLower === 'true' || valueLower === 'yes' || valueLower === 'on'; | ||
} | ||
|
||
// Open the `Settings` menu. | ||
document.querySelector('ytp-settings-button, .ytp-settings-button').click(); | ||
const prefs = { | ||
hd: false, | ||
quality: 1440, | ||
log: qs.get('mozDebug') ? getTruthyQS('mozDebug') : true, | ||
retryAttempts: parseInt(qs.get('retryAttempts') || qs.get('retryattempts') || '5', 10), | ||
retryTimeout: parseInt(qs.get('retryTimeout') || qs.get('retrytimeout') || '500', 10) | ||
}; | ||
|
||
const printLog = String(prefs.log) === 'true'; | ||
|
||
const log = (...args) => printLog && console.log(LOGTAG, ...args); | ||
const logError = (...args) => printLog && console.error(LOGTAG, ...args); | ||
const logWarn = (...args) => printLog && console.warn(LOGTAG, ...args); | ||
|
||
const ytImprover = window.ytImprover = (state, attempts) => { | ||
if (ytImprover.completed) { | ||
return; | ||
} | ||
|
||
if (typeof attempts === 'undefined') { | ||
attempts = 1; | ||
} | ||
if (attempts >= prefs.retryAttempts) { | ||
return; | ||
} | ||
|
||
const player = document.getElementById('movie_player'); | ||
if (state !== 1 || !player) { | ||
attempts++; | ||
retryTimeout = setTimeout(() => { | ||
ytImprover(state, attempts); | ||
}, prefs.retryInterval); | ||
return; | ||
} | ||
|
||
const levels = player.getAvailableQualityLevels(); | ||
if (!levels || !levels.length) { | ||
logWarn('Cannot read `player.getAvailableQualityLevels()`'); | ||
return; | ||
} | ||
|
||
clearTimeout(retryTimeout); | ||
ytImprover.completed = true; | ||
|
||
const prefs.qualities = [ | ||
'highres', 'h2880', 'hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto' | ||
]; | ||
const prefs.qualityLabels = { | ||
'4320': 'highres', // 8K / 4320p / QUHD | ||
'2880': 'hd2880', // 5K / 2880p / UHD+ | ||
'2160': 'hd2160', // 4K / 2160p / UHD | ||
'1440': 'hd1440', // 1440p / QHD | ||
'1080': 'hd1080', // 1080p / FHD | ||
'720': 'hd720', // 720p / HD | ||
'480': 'large', // 480p | ||
'360': 'medium', // 360p | ||
'240': 'small', // 240p | ||
'144': 'tiny', // 144p | ||
'0': 'auto' | ||
}; | ||
|
||
// Select the `Quality` sub-menu. | ||
document.querySelector('ytp-settings-menu ytp-menuitem:last-child, .ytp-settings-menu .ytp-menuitem:last-child').click(); | ||
const getDesiredQuality = () => { | ||
const qsQuality = (qs.get('vq') || qs.get('quality') || '').trim().toLowerCase(); | ||
if (qsQuality) { | ||
if (qsQuality in prefs.qualityLabels) { | ||
prefs.quality = prefs.qualityLabels[qsQuality]; | ||
} else { | ||
const qsQualityNumber = parseInt(qsQuality, 10); | ||
if (Number.isInteger(qsQualityNumber)) { | ||
prefs.quality = qsQualityNumber; | ||
} else { | ||
prefs.quality = qsQuality; | ||
} | ||
} | ||
} | ||
prefs.quality = String(prefs.quality).toLowerCase(); | ||
if (qsQuality === 'auto' || qsQuality === 'default') { | ||
prefs.quality = 'auto'; | ||
} | ||
if (prefs.quality in prefs.qualityLabels) { | ||
prefs.quality = prefs.qualityLabels[prefs.quality]; | ||
} | ||
return prefs.quality; | ||
}; | ||
|
||
// Select the best `Quality`. | ||
document.querySelector('ytp-quality-menu ytp-menuitem:first-child, .ytp-quality-menu .ytp-menuitem:first-child').click(); | ||
prefs.quality = getDesiredQuality(); | ||
if (prefs.quality === 'auto') { | ||
return log(`Desired quality is fine (${prefs.quality})`); | ||
} | ||
|
||
const currentQuality = player.getPlaybackQuality(); | ||
if (prefs.quality === currentQuality) { | ||
return log(`Current quality is desired quality (${currentQuality})`); | ||
} | ||
|
||
const findBestQuality = increase => { | ||
if (prefs.quality === 'highest' || prefs.quality === 'best' || prefs.quality === 'max' || prefs.quality === 'maximum') { | ||
return levels[0]; | ||
} | ||
if (prefs.quality === 'lowest' || prefs.quality === 'worst' || prefs.quality === 'min' || prefs.quality === 'minimum') { | ||
return levels[levels.length - 1]; | ||
} | ||
if (increase) { | ||
prefs.quality = prefs.qualities[prefs.qualities.indexOf(prefs.quality) - 1] || levels[0]; | ||
} | ||
const index = levels.indexOf(prefs.quality); | ||
if (index !== -1) { | ||
return prefs.quality; | ||
} | ||
return findBestQuality(true); | ||
}; | ||
const newBestQuality = findBestQuality(); | ||
if (currentQuality === newBestQuality) { | ||
return log(`Current quality "${currentQuality}" is the best available quality`); | ||
} | ||
|
||
if (!player.setPlaybackQuality) { | ||
return logError('`player.setPlaybackQuality` not available'); | ||
} | ||
player.setPlaybackQuality(newBestQuality); | ||
|
||
if (!player.setPlaybackQualityRange) { | ||
return logError('`player.setPlaybackQualityRange` not available'); | ||
} | ||
try { | ||
player.setPlaybackQualityRange(newBestQuality, newBestQuality); | ||
} catch (e) { | ||
} | ||
|
||
log(`Changed quality from "${currentQuality}" to "${newBestQuality}"`); | ||
}; | ||
|
||
if (window.location.pathname.startsWith('/watch')) { | ||
const onYouTubePlayerReady = window.onYouTubePlayerReady = evt => { | ||
log('`onYouTubePlayerReady` called'); | ||
window.ytImprover(1); | ||
evt.addEventListener('onStateChange', 'ytImprover'); | ||
}; | ||
|
||
window.addEventListener('spfready', () => { | ||
log('`spfready` event fired'); | ||
if (typeof window.ytplayer === 'object' && window.ytplayer.config) { | ||
log('`window.ytplayer.config.args.jsapicallback` set'); | ||
window.ytplayer.config.args.jsapicallback = 'onYouTubePlayerReady'; | ||
} | ||
}); | ||
|
||
ytImprover(1); | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters