YouTube Permanent ProgressBar

Keeps YouTube progress bar visible all the time.

当前为 2022-03-05 提交的版本,查看 最新版本

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址