YouTube Permanent ProgressBar

Keeps YouTube progressbar visible all the time.

当前为 2021-05-10 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube Permanent ProgressBar
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Keeps YouTube progressbar visible all the time.
// @author       Can Kurt
// @match        *://www.youtube.com/*
// @license      MIT
// ==/UserScript==


var permanentProgressBar = {

    setup : function(){
        // keep progressBar visible with css
        document.querySelector(".ytp-chrome-bottom").style.cssText = "opacity: 1 !important;";
    },

    prettifyVideoTime : function(video){
        let seconds = "" + Math.floor(video.currentTime%60);
        let minutes = "" + Math.floor((video.currentTime%3600)/60);
        let hours = "" + Math.floor(video.currentTime/3600);
        if(video.currentTime/60 > 60){
            return `${hours}:${minutes.padStart(2, '0')}:${seconds.padStart(2, '0')}`;
        }
        else{
            return `${minutes}:${seconds.padStart(2, '0')}`;
        }
    },

    getDuration : function(video, type){
        if(type === "PROGRESSBAR"){
            return video.currentTime;
        }
        else if(type === "BUFFERBAR"){
            return video.buffered.end(video.buffered.length-1);
        }
    },

    updateCurrentTimeField : function(player){
        const video = player.querySelector("video");
        const currentTime = player.querySelector(".ytp-time-current");
        if (!video || !currentTime) {
            return;
        }

        currentTime.innerText = permanentProgressBar.prettifyVideoTime(video);
    },

    updateProgressBar : function(player){
        // works only on chapterless (old) videos
        const video = player.querySelector("video");
        const progressBar = player.querySelector(".ytp-play-progress");
        const bufferBar = player.querySelector(".ytp-load-progress");
        if (!video || !progressBar || !bufferBar) {
            return;
        }

        progressBar.style.transform = `scaleX(${video.currentTime/video.duration})`;
        bufferBar.style.transform = `scaleX(${video.buffered.end(video.buffered.length-1)/video.duration})`;
    },

    updateProgressBarWithChapters : function(player, type){
        // YouTube api does not provides current time in chapters
        // this function finds current time in the chapter by finding the ratio between total video duration and total width of the chapters div

        const video = player.querySelector("video");

        // there can be multiple chapters
        const progressBarWidthsCollection = player.getElementsByClassName("ytp-progress-bar-padding");

        // select progress or bufferBar
        let progressBarChaptersCollection;
        if(type === "PROGRESSBAR"){
            progressBarChaptersCollection = player.getElementsByClassName("ytp-play-progress");
        }
        if(type === "BUFFERBAR"){
            progressBarChaptersCollection = player.getElementsByClassName("ytp-load-progress");
        }

        // quit if elements does not exists
        if (!video || !progressBarWidthsCollection || !progressBarChaptersCollection) {
            return;
        }

        // find the ratio between total video duration and total width of the chapters div
        let totalProgressBarWidth = 0;
        for (let i = 0; i < progressBarWidthsCollection.length; i++) {
            totalProgressBarWidth += progressBarWidthsCollection[i].offsetWidth;
        }
        const durationWidthRatio = video.duration/totalProgressBarWidth;

        // loop inside chapters
        let chaptersPixelWidthUntilCurrentChapter = 0;
        for (let i = 0; i < progressBarWidthsCollection.length; i++) {

            // if current time is bigger than durationWidthRatio * (chapters pixel width including current one) scale the current chapter to 1 because we passed it
            if(permanentProgressBar.getDuration(video, type) > durationWidthRatio*(chaptersPixelWidthUntilCurrentChapter + progressBarWidthsCollection[i].offsetWidth)){
                progressBarChaptersCollection[i].style.transform = "scaleX(1)";

                // increase the current chapters location by adding last watched chapter
                chaptersPixelWidthUntilCurrentChapter += progressBarWidthsCollection[i].offsetWidth;
            }

            // If not, it means that we are on this chapter.
            // Find the appropriate size for the chapter and scale it
            else{
                // current time
                let currentTimeInChapterInSeconds = permanentProgressBar.getDuration(video, type) - (durationWidthRatio*chaptersPixelWidthUntilCurrentChapter);

                // total chapter time
                let currentChapterLengthInSeconds = durationWidthRatio*progressBarWidthsCollection[i].offsetWidth;

                let currentChapterTimeRatio = currentTimeInChapterInSeconds / currentChapterLengthInSeconds

                progressBarChaptersCollection[i].style.transform = `scaleX(${currentChapterTimeRatio})`;

                break;
            }

        }

    },

    update : function(){
        const player = document.querySelector(".html5-video-player");
        if (!player) {
            return;
        }

        // update video timer
        permanentProgressBar.updateCurrentTimeField(player);

        // update progressBars
        permanentProgressBar.updateProgressBarWithChapters(player, "PROGRESSBAR");

        permanentProgressBar.updateProgressBarWithChapters(player, "BUFFERBAR");

    },

    start : function(){
        permanentProgressBar.setup();
        setInterval(permanentProgressBar.update, 500);
    }

}


permanentProgressBar.start();