您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show the remaining time of a YouTube video inside the player.
当前为
// ==UserScript== // @name YouTube Remaining Time // @namespace http://the6p4c.com/ // @version 1.2 // @description Show the remaining time of a YouTube video inside the player. // @author The6P4C // @match *://www.youtube.com/* // @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js // @grant none // ==/UserScript== // *********************************************************************** // CHANGE TO true TO DISPLAY REMAINING TIME COMPENSATING FOR PLAYBACK RATE // *********************************************************************** var SHOW_REAL_TIME_REMAINING = false; var TIME_KEYS_ORDER = ["days", "hours", "minutes", "seconds"]; var TIME_KEYS_ORDER_REV = [].concat(TIME_KEYS_ORDER).reverse(); function parseTime(timeString) { // reversed so seconds first var parts = timeString.split(":").reverse(); var time = {}; for (var i = 0; i < TIME_KEYS_ORDER_REV.length; ++i) { var key = TIME_KEYS_ORDER_REV[i]; if (i < parts.length) { time[key] = parseInt(parts[i]); } else { time[key] = 0; } } return time; } function pad2(n) { if (n >= 10) { return n; } else { return "0" + n; } } function stringifyTime(time) { var timeString = ""; var nonZeroEncountered = false; for (var i = 0; i < TIME_KEYS_ORDER.length; ++i) { var key = TIME_KEYS_ORDER[i]; var currentValue = time[key]; // Only start adding values from the first non zero // But... always show minutes, even if they're zero. if (currentValue !== 0 || nonZeroEncountered || key == "minutes") { // We don't want to pad the first value: // If there's hours, don't pad days // If there's minutes, don't pad hours // If there's seconds, don't pad minutes if (nonZeroEncountered) { currentValue = pad2(currentValue); } timeString += currentValue; if (key != "seconds") { timeString += ":"; } nonZeroEncountered = true; } } return timeString; } function subtractTime(a, b) { var secondsDiff = a.seconds - b.seconds; var minutesDiff = a.minutes - b.minutes; var hoursDiff = a.hours - b.hours; var daysDiff = a.days - b.days; if (secondsDiff < 0) { minutesDiff -= 1; secondsDiff += 60; } if (minutesDiff < 0) { hoursDiff -= 1; minutesDiff += 60; } if (hoursDiff < 0) { daysDiff -= 1; hoursDiff += 24; } return { days: daysDiff, hours: hoursDiff, minutes: minutesDiff, seconds: secondsDiff }; } function divideTime(time, divisor) { var timeSeconds = time.seconds + ((time.minutes + (time.hours + time.days * 24) * 60) * 60); var newTimeSeconds = Math.floor(timeSeconds / divisor); return { days: Math.floor(newTimeSeconds / (24 * 60 * 60)), hours: Math.floor(newTimeSeconds / (60 * 60)), minutes: Math.floor(newTimeSeconds / 60), seconds: newTimeSeconds % 60 }; } function tryGetPlaybackRate($timeDisplay) { // Try and find the playback speed from the settings UI var $ytdPlayer = $timeDisplay.parents(".html5-video-player"); if ($ytdPlayer.length != 1) { // If we can't find the player, fall back to a "safe" alternative return 1; } $ytdPlayer = $ytdPlayer[0]; // We can't be sure that this will work - if YouTube changes their player API somehow // we don't want our entire script to break. Again, fall back to a "safe" alternative. try { return $ytdPlayer.getPlaybackRate(); } catch (e) { return 1; } } function onTimeChange() { var $this = $(this); // If this event was called in the context of the .ytp-time-duration event, // we need to set $timeCurrent not to $this but to the actual // .ytp-time-current element. var $timeCurrent = $this; if (!$this.hasClass("ytp-time-current")) { $timeCurrent = $this.parent().find(".ytp-time-current"); } var $timeDisplay = $timeCurrent.parent(); // For some reason a time will show on a live video, but I don't think it's very meaningful if ($timeDisplay.hasClass("ytp-live")) { return; } var $timeDuration = $timeDisplay.parent().find(".ytp-time-duration"); if ($timeDisplay.attr("____remaining-added") != "____remaining-added") { var $timeRemainingWrapper = $("<div style='display: inline-block; width: 5px;'></div><span style='color: #ddd; text-shadow: 0 0 2px rgba(0,0,0,.5)'>(-<span class='____time-remaining'></span>)</span>"); $timeDuration.after($timeRemainingWrapper); $timeDisplay.attr("____remaining-added", "____remaining-added"); } var $timeRemaining = $timeDisplay.find(".____time-remaining"); var currentTime = parseTime($timeCurrent.text()); var durationTime = parseTime($timeDuration.text()); var remainingTime = subtractTime(durationTime, currentTime); if (SHOW_REAL_TIME_REMAINING) { var playbackRate = tryGetPlaybackRate($timeDisplay); var remainingRealTime = divideTime(remainingTime, playbackRate); var suffix = playbackRate == 1 ? "" : (" at x" + playbackRate); $timeRemaining.text(stringifyTime(remainingRealTime) + suffix); } else { $timeRemaining.text(stringifyTime(remainingTime)); } } $(document).ready(function() { $("body").on("DOMSubtreeModified", ".ytp-time-current", onTimeChange); $("body").on("DOMSubtreeModified", ".ytp-time-duration", onTimeChange); });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址