您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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.2.11 // @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) //===== CONFIGURATION END ===== var timerWaitInfo, timerProgressMonitor, timerWaitPlayer, timerDoubleCheck, playerManager; function processInfo() { if (window.vidprogress || (location.pathname !== "/watch")) return; clearTimeout(timerWaitInfo); (function waitInfo(a, b) { if (a = document.querySelector("#info-contents #info, #watch7-user-header")) { b = document.createElement("SPAN"); b.id = "vidprogress"; b.innerHTML = '<span id="curq" style="font-weight:500"></span><span id="curtime" style="display:inline-block;margin-left:1ex"></span>'; b.style.cssText = "margin-left:1ex;border:1px solid #ccc;border-radius:4px;padding:2px;background:#eee;text-align:center;font-size:9pt"; if (window["body-container"]) { a.appendChild(b); } else a.insertBefore(b, 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){ 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); });