Greasy Fork is available in English.
Add progress bar at bottom of YouTube video and progress text on the video page. On the progress text, the current video quality will have a "+" suffix if there's a higher one available. Hovering the mouse cursor onto the video quality text will show the current and available video quality IDs.
当前为
// ==UserScript==
// @name Add YouTube Video Progress
// @namespace http://greasyfork.icu/en/users/85671-jcunews
// @version 1.3.12
// @license GNU AGPLv3
// @author jcunews
// @description Add progress bar at bottom of YouTube video and progress text on the video page. On the progress text, the current video quality will have a "+" suffix if there's a higher one available. Hovering the mouse cursor onto the video quality text will show the current and available video quality IDs.
// @match https://www.youtube.com/*
// @grant none
// @run-at document-start
// ==/UserScript==
//===== CONFIGURATION BEGIN =====
var progressbarHeight = 2; //in pixels
var progressbarColor = "#fff"; //e.g. "#fff" or "#e0e0e0" or "cyan"
var progressbarElapsedColor = "#f00";
var progressbarBufferColor = "#77f";
var contentLoadProcessDelay = 0; //number of milliseconds before processing dynamically loaded contents (increase if slow network/browser)
//styles for progress text (non dark mode)
var progressTextStyles = "margin-left:1ex;border:1px solid #ccc;border-radius:4px;padding:2px;background:#eee;text-align:center;font-size:9pt";
//styles for progress text (dark mode)
var progressTextStylesDark = "margin-left:1ex;border:1px solid #eee;border-radius:4px;padding:2px;background:#111;text-align:center;font-size:9pt;color:#eee";
//===== CONFIGURATION END =====
var timerWaitInfo, timerProgressMonitor, timerWaitPlayer, timerDoubleCheck, playerManager, eleProgressText;
function processInfo() {
if (window.vidprogress || (location.pathname !== "/watch")) return;
clearTimeout(timerWaitInfo);
(function waitInfo(a) {
if (a = document.querySelector("#info-contents #info, #watch7-user-header")) {
eleProgressText = document.createElement("SPAN");
eleProgressText.id = "vidprogress";
eleProgressText.innerHTML = '<span id="curq" style="font-weight:500"></span><span id="curtime" style="display:inline-block;margin-left:1ex"></span>';
eleProgressText.style.cssText = document.documentElement.attributes["dark"] ? progressTextStylesDark : progressTextStyles;
if (window["body-container"]) {
a.appendChild(eleProgressText);
} else a.insertBefore(eleProgressText, a.querySelector("#flex"));
} else timerWaitInfo = setTimeout(waitInfo, 200);
})();
}
function processPlayer() {
function zerolead(n){
return n > 9 ? n : "0" + n;
}
function sec2hms(sec) {
var c = sec % 60, d = Math.floor(sec / 60);
return (d >= 60 ? zerolead(Math.floor(d / 60)) + ":" : "") + zerolead(d % 60) + ":" + zerolead(c);
}
function updProgress(a, b, c, d, ls){
if (document.documentElement.attributes["dark"]) {
if (eleProgressText.style.cssText !== progressTextStylesDark) eleProgressText.style.cssText = progressTextStylesDark;
} else if (eleProgressText.style.cssText !== progressTextStyles) eleProgressText.style.cssText = progressTextStyles;
a = window.movie_player;
if (a && window.vidprogress2b && a.getCurrentTime) try {
if (window.curtime) {
b = a.getPlaybackQuality();
switch (b) {
case "light":
case "tiny": c = "144p"; break;
case "small": c = "240p"; break;
case "medium": c = "360p"; break;
case "large": c = "480p"; break;
case "highres": c = "4320p"; break;
default:
if (ls = b.match(/^hd(\d+)/)) {
c = ls[1] + "p";
} else c = b;
}
(d = a.getAvailableQualityLevels()).pop();
curq.textContent = c + (d.indexOf(b) > 0 ? "+" : "");
curq.title = `Current: ${b}\nAvailable: ${d}`;
}
b = a.getCurrentTime();
if (b >= 0) {
ls = a.getDuration();
if (!a.getVideoData().isLive) {
if (window.curtime) {
curtime.textContent = sec2hms(Math.floor(b)) + " / " + sec2hms(Math.floor(ls)) + " (" + Math.floor(b * 100 / ls) + "%)";
}
vidprogress2b.style.width = Math.ceil((b / ls) * vidprogress2.offsetWidth) + "px";
vidprogress2c.style.width = Math.ceil((a.getVideoBytesLoaded() / a.getVideoBytesTotal()) * vidprogress2.offsetWidth) + "px";
} else {
if (window.curtime) {
curtime.textContent = "LIVE";
}
vidprogress2b.style.width = "100%";
}
} else {
if (window.curtime) {
curq.textContent = "";
curtime.textContent = "";
}
vidprogress2b.style.width = "0px";
vidprogress2c.style.width = "0px";
}
}catch(a){
if (window.curtime) {
curq.textContent = "[???]";
curtime.textContent = "???";
}
vidprogress2b.style.width = "0px";
vidprogress2c.style.width = "0px";
}
}
function resumeProgressMonitor() {
if (timerProgressMonitor) return;
updProgress();
timerProgressMonitor = setInterval(updProgress, 200);
}
function pauseProgressMonitor() {
clearInterval(timerProgressMonitor);
timerProgressMonitor = 0;
updProgress();
}
clearInterval(timerProgressMonitor);
timerProgressMonitor = 0;
clearTimeout(timerWaitPlayer);
timerWaitPlayer = 0;
clearInterval(timerDoubleCheck);
timerDoubleCheck = 0;
(function waitPlayer() {
if (!window.vidprogress2 && window.movie_player && (a = movie_player.parentNode.querySelector("video"))) {
b = document.createElement("DIV");
b.id = "vidprogress2";
b.style.cssText = "opacity:.66;position:absolute;z-index:10;bottom:0;width:100%;height:" + progressbarHeight + "px;background:" + progressbarColor;
b.innerHTML = `
<div id="vidprogress2c" style="position:absolute;height:100%;background:${progressbarBufferColor}"></div>
<div id="vidprogress2b" style="position:absolute;height:100%;background:${progressbarElapsedColor}"></div>`;
movie_player.appendChild(b);
if (movie_player.getPlayerState() === 1) {
resumeProgressMonitor();
}
//useful: onLoadedMetadata(), onStateChange(state), onPlayVideo(info), onReady(playerApi), onVideoAreaChange(), onVideoDataChange(info)
//states: -1=notReady, 0=ended, 1=playing, 2=paused, 3=ready, 4=???, 5=notAvailable?
movie_player.addEventListener("onLoadedMetadata", resumeProgressMonitor);
movie_player.addEventListener("onStateChange", function(state) {
if (state === 1) {
resumeProgressMonitor();
} else pauseProgressMonitor();
});
} else timerWaitPlayer = setTimeout(waitPlayer, 200);
})();
function doubleCheck() {
if (window.movie_player && movie_player.getPlayerState) {
if (movie_player.getPlayerState() === 1) {
resumeProgressMonitor();
} else pauseProgressMonitor();
}
}
if (!timerDoubleCheck) timerDoubleCheck = setInterval(doubleCheck, 500);
}
addEventListener("yt-page-data-updated", processInfo);
addEventListener("yt-player-released", processPlayer);
addEventListener("load", function() {
processInfo();
processPlayer();
});
addEventListener("spfprocess", function() {
setTimeout(function() {
processInfo();
processPlayer();
}, contentLoadProcessDelay);
});