YouTube Permanent ProgressBar

Keeps YouTube progressbar visible all the time.

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

  1. // ==UserScript==
  2. // @name YouTube Permanent ProgressBar
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Keeps YouTube progressbar visible all the time.
  6. // @author Can Kurt
  7. // @match *://www.youtube.com/*
  8. // @license MIT
  9. // ==/UserScript==
  10.  
  11.  
  12. var permanentProgressBar = {
  13.  
  14. setup : function(){
  15. // keep progressBar visible with css
  16. document.querySelector(".ytp-chrome-bottom").style.cssText = "opacity: 1 !important;";
  17. },
  18.  
  19. prettifyVideoTime : function(video){
  20. let seconds = "" + Math.floor(video.currentTime%60);
  21. let minutes = "" + Math.floor((video.currentTime%3600)/60);
  22. let hours = "" + Math.floor(video.currentTime/3600);
  23. if(video.currentTime/60 > 60){
  24. return `${hours}:${minutes.padStart(2, '0')}:${seconds.padStart(2, '0')}`;
  25. }
  26. else{
  27. return `${minutes}:${seconds.padStart(2, '0')}`;
  28. }
  29. },
  30.  
  31. getDuration : function(video, type){
  32. if(type === "PROGRESSBAR"){
  33. return video.currentTime;
  34. }
  35. else if(type === "BUFFERBAR"){
  36. return video.buffered.end(video.buffered.length-1);
  37. }
  38. },
  39.  
  40. updateCurrentTimeField : function(player){
  41. const video = player.querySelector("video");
  42. const currentTime = player.querySelector(".ytp-time-current");
  43. if (!video || !currentTime) {
  44. return;
  45. }
  46.  
  47. currentTime.innerText = permanentProgressBar.prettifyVideoTime(video);
  48. },
  49.  
  50. updateProgressBar : function(player){
  51. // works only on chapterless (old) videos
  52. const video = player.querySelector("video");
  53. const progressBar = player.querySelector(".ytp-play-progress");
  54. const bufferBar = player.querySelector(".ytp-load-progress");
  55. if (!video || !progressBar || !bufferBar) {
  56. return;
  57. }
  58.  
  59. progressBar.style.transform = `scaleX(${video.currentTime/video.duration})`;
  60. bufferBar.style.transform = `scaleX(${video.buffered.end(video.buffered.length-1)/video.duration})`;
  61. },
  62.  
  63. updateProgressBarWithChapters : function(player, type){
  64. // YouTube api does not provides current time in chapters
  65. // this function finds current time in the chapter by finding the ratio between total video duration and total width of the chapters div
  66.  
  67. const video = player.querySelector("video");
  68.  
  69. // there can be multiple chapters
  70. const progressBarWidthsCollection = player.getElementsByClassName("ytp-progress-bar-padding");
  71.  
  72. // select progress or bufferBar
  73. let progressBarChaptersCollection;
  74. if(type === "PROGRESSBAR"){
  75. progressBarChaptersCollection = player.getElementsByClassName("ytp-play-progress");
  76. }
  77. if(type === "BUFFERBAR"){
  78. progressBarChaptersCollection = player.getElementsByClassName("ytp-load-progress");
  79. }
  80.  
  81. // quit if elements does not exists
  82. if (!video || !progressBarWidthsCollection || !progressBarChaptersCollection) {
  83. return;
  84. }
  85.  
  86. // find the ratio between total video duration and total width of the chapters div
  87. let totalProgressBarWidth = 0;
  88. for (let i = 0; i < progressBarWidthsCollection.length; i++) {
  89. totalProgressBarWidth += progressBarWidthsCollection[i].offsetWidth;
  90. }
  91. const durationWidthRatio = video.duration/totalProgressBarWidth;
  92.  
  93. // loop inside chapters
  94. let chaptersPixelWidthUntilCurrentChapter = 0;
  95. for (let i = 0; i < progressBarWidthsCollection.length; i++) {
  96.  
  97. // if current time is bigger than durationWidthRatio * (chapters pixel width including current one) scale the current chapter to 1 because we passed it
  98. if(permanentProgressBar.getDuration(video, type) > durationWidthRatio*(chaptersPixelWidthUntilCurrentChapter + progressBarWidthsCollection[i].offsetWidth)){
  99. progressBarChaptersCollection[i].style.transform = "scaleX(1)";
  100.  
  101. // increase the current chapters location by adding last watched chapter
  102. chaptersPixelWidthUntilCurrentChapter += progressBarWidthsCollection[i].offsetWidth;
  103. }
  104.  
  105. // If not, it means that we are on this chapter.
  106. // Find the appropriate size for the chapter and scale it
  107. else{
  108. // current time
  109. let currentTimeInChapterInSeconds = permanentProgressBar.getDuration(video, type) - (durationWidthRatio*chaptersPixelWidthUntilCurrentChapter);
  110.  
  111. // total chapter time
  112. let currentChapterLengthInSeconds = durationWidthRatio*progressBarWidthsCollection[i].offsetWidth;
  113.  
  114. let currentChapterTimeRatio = currentTimeInChapterInSeconds / currentChapterLengthInSeconds
  115.  
  116. progressBarChaptersCollection[i].style.transform = `scaleX(${currentChapterTimeRatio})`;
  117.  
  118. break;
  119. }
  120.  
  121. }
  122.  
  123. },
  124.  
  125. update : function(){
  126. const player = document.querySelector(".html5-video-player");
  127. if (!player) {
  128. return;
  129. }
  130.  
  131. // update video timer
  132. permanentProgressBar.updateCurrentTimeField(player);
  133.  
  134. // update progressBars
  135. permanentProgressBar.updateProgressBarWithChapters(player, "PROGRESSBAR");
  136.  
  137. permanentProgressBar.updateProgressBarWithChapters(player, "BUFFERBAR");
  138.  
  139. },
  140.  
  141. start : function(){
  142. permanentProgressBar.setup();
  143. setInterval(permanentProgressBar.update, 500);
  144. }
  145.  
  146. }
  147.  
  148.  
  149. permanentProgressBar.start();