您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Always show progress bar
// ==UserScript== // @name YouTube Always show progress bar - Forked // @version 2024.02.14 // @author Xiao // @match *://www.youtube.com/* // @allFrames true // @grant unsafeWindow // @namespace https://greasyfork.org/users/5802 // @description Always show progress bar // ==/UserScript== //original: https://greasyfork.org/en/scripts/30046-youtube-always-show-progress-bar let css = ` .ytp-autohide .ytp-chrome-bottom { opacity: 1 !important; } .ytp-autohide .ytp-chrome-bottom .ytp-progress-bar-container[alwaysshow="true"] { bottom:-1px; } .ytp-autohide .ytp-chrome-bottom > :not(.ytp-progress-bar-container[alwaysshow="true"]) { display: none; } `; let style = document.createElement('style'); style.textContent = css; document.head.appendChild(style); let eventHandlers = []; let timeupdateListener; let progressListener; let video; setTimeout(run, 2000); function isFinished() { video = document.querySelector('video'); if (video) { eventHandlers[0]?.removeEventListener('timeupdate', eventHandlers[1]); eventHandlers[0]?.removeEventListener('progress', eventHandlers[2]); setTimeout(run, 2000); } else if (location.pathname === '/watch') { setTimeout(isFinished, 1000); } } addEventListener('yt-navigate-finish', isFinished); function run () { if (document.querySelector('#movie_player.ad-showing')) { setTimeout(run, 2000); return; } video = document.querySelector('video'); if (!document.querySelector('.html5-video-player:not(.addedupdateevents)')) return; let ytdApp = unsafeWindow.document.querySelector('ytd-app'); let chap, isLive; if (ytdApp) { let data = ytdApp.__data.data.response; chap = data.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer?.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap?.find(exportFunction(a => a.key == 'AUTO_CHAPTERS' || a.key == 'DESCRIPTION_CHAPTERS', unsafeWindow)).value.chapters; isLive = data.contents.twoColumnWatchNextResults.results.results.contents[0].videoPrimaryInfoRenderer.viewCount.videoViewCountRenderer?.isLive; } else { let data = unsafeWindow.ytPubsubPubsubInstance.h[33].player.app.mediaElement.ra.videoData; chap = data.Ua?.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer?.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap?.find(exportFunction(a => a.key == 'AUTO_CHAPTERS' || a.key == 'DESCRIPTION_CHAPTERS', unsafeWindow)).value.chapters; isLive = data.isLivePlayback; } document.querySelector('.ytp-progress-bar-container').setAttribute('alwaysshow', !isLive); video.className += ' addedupdateevents'; let player = document.getElementById('movie_player'); let progressbars = document.querySelectorAll('.ytp-play-progress'); let loadbars = document.querySelectorAll('.ytp-load-progress'); if (chap?.length) { let chars = []; let cap; let capstart; let capduration; let lastusedcapprog; let lastusedcapbuf; for (let i = 0; i < chap.length; i++) { chars.push(chap[i].chapterRenderer.timeRangeStartMillis / 1000); } timeupdateListener = () => { if (!player.classList.contains('ytp-autohide')) return; for (let i = 0; i < chars.length; i++) { let ts = chars[i]; if (ts < video.currentTime || !capduration) { cap = i; capstart = ts; capduration = ((chars[i + 1] ? chars[i + 1] : video.duration) - ts); } else { break; } } if (cap > lastusedcapprog) progressbars[lastusedcapprog].style.transform = 'scaleX(1)'; lastusedcapprog = cap; progressbars[cap].style.transform = 'scaleX(' + ((video.currentTime - capstart) / capduration) + ')'; }; video.addEventListener('timeupdate', timeupdateListener); progressListener = () => { if (!player.classList.contains('ytp-autohide') || !video.buffered.length) return; let buff = video.buffered.end(video.buffered.length - 1); for (let i = 0; i < chars.length; i++) { let ts = chars[i]; if (ts < buff || !capduration) { cap = i; capstart = ts; capduration = ((chars[i + 1] ? chars[i + 1] : video.duration) - ts); } else { break; } } if (cap > lastusedcapbuf) loadbars[lastusedcapbuf].style.transform = 'scaleX(1)'; lastusedcapbuf = cap; loadbars[cap].style.transform = 'scaleX(' + ((buff - capstart) / capduration) + ')'; }; video.addEventListener('progress', progressListener); eventHandlers = [video, timeupdateListener, progressListener]; } else { timeupdateListener = function () { if (player.classList.contains('ytp-autohide')) progressbars[0].style.transform = 'scaleX(' + (video.currentTime / video.duration) + ')'; }; video.addEventListener('timeupdate', timeupdateListener); progressListener = function () { if (player.classList.contains('ytp-autohide') && video.buffered.length) loadbars[0].style.transform = 'scaleX(' + (video.buffered.end(video.buffered.length - 1) / video.duration) + ')'; }; video.addEventListener('progress', progressListener); eventHandlers = [video, timeupdateListener, progressListener]; } }