YouTube Always show progress bar - Forked

Always show progress bar

目前为 2022-10-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Always show progress bar - Forked
  3. // @version 2022.10.25
  4. // @author Xiao
  5. // @match *://www.youtube.com/*
  6. // @allFrames true
  7. // @grant unsafeWindow
  8. // @namespace https://greasyfork.org/users/5802
  9. // @description Always show progress bar
  10. // ==/UserScript==
  11.  
  12. //original: https://greasyfork.org/en/scripts/30046-youtube-always-show-progress-bar
  13.  
  14. let css = `
  15. .ytp-autohide .ytp-chrome-bottom {
  16. opacity: 1 !important;
  17. }
  18.  
  19. .ytp-autohide .ytp-chrome-bottom .ytp-progress-bar-container[alwaysshow="true"] {
  20. bottom:-1px;
  21. }
  22.  
  23. .ytp-autohide .ytp-chrome-bottom > :not(.ytp-progress-bar-container[alwaysshow="true"]) {
  24. display: none;
  25. }
  26. `;
  27.  
  28. let style = document.createElement('style');
  29. style.textContent = css;
  30. document.head.appendChild(style);
  31.  
  32. let eventHandlers = [];
  33.  
  34. let timeupdateListener;
  35. let progressListener;
  36. let video;
  37.  
  38. setTimeout(run, 2000);
  39.  
  40. addEventListener('yt-navigate-finish', function() {
  41. video = document.querySelector('video');
  42. if (video) {
  43. eventHandlers[0]?.removeEventListener('timeupdate', eventHandlers[1]);
  44. eventHandlers[0]?.removeEventListener('progress', eventHandlers[2]);
  45. setTimeout(run, 2000);
  46. }
  47. });
  48.  
  49. function run () {
  50. if (document.querySelector('#movie_player.ad-showing')) {
  51. setTimeout(run, 2000);
  52. return;
  53. }
  54.  
  55. video = document.querySelector('video');
  56. if (/*!video?.src || */!document.querySelector('.html5-video-player:not(.addedupdateevents)'))
  57. return;
  58.  
  59. let videoData = Object.values((unsafeWindow.ytPubsubPubsubInstance.i/*embed*/ || unsafeWindow.ytPubsubPubsubInstance.j/*normal*/ || unsafeWindow.ytPubsubPubsubInstance.subscriptions_/*navigation*/).find(exportFunction(a => a?.player, unsafeWindow)).player.app.Ib).find(exportFunction(a => a?.videoData, unsafeWindow)).videoData;
  60. document.querySelector('.ytp-progress-bar-container').setAttribute('alwaysshow', !videoData.isLivePlayback);
  61.  
  62. video.className += ' addedupdateevents';
  63. let player = document.getElementById('movie_player');
  64. let progressbars = document.querySelectorAll('.ytp-play-progress');
  65. let loadbars = document.querySelectorAll('.ytp-load-progress');
  66.  
  67. let chap = videoData.multiMarkersPlayerBarRenderer?.markersMap[0].value.chapters;
  68.  
  69. if (chap?.length) {
  70. let chars = [];
  71. let cap;
  72. let capstart;
  73. let capduration;
  74. let lastusedcapprog;
  75. let lastusedcapbuf;
  76.  
  77. for (let i = 0; i < chap.length; i++) {
  78. chars.push(chap[i].chapterRenderer.timeRangeStartMillis / 1000);
  79. }
  80.  
  81. timeupdateListener = () => {
  82. if (!player.classList.contains('ytp-autohide'))
  83. return;
  84.  
  85. for (let i = 0; i < chars.length; i++) {
  86. let ts = chars[i];
  87. if (ts < video.currentTime || !capduration) {
  88. cap = i;
  89. capstart = ts;
  90. capduration = ((chars[i + 1] ? chars[i + 1] : video.duration) - ts);
  91. } else {
  92. break;
  93. }
  94. }
  95.  
  96. if (cap > lastusedcapprog)
  97. progressbars[lastusedcapprog].style.transform = 'scaleX(1)';
  98.  
  99. lastusedcapprog = cap;
  100.  
  101. progressbars[cap].style.transform = 'scaleX(' + ((video.currentTime - capstart) / capduration) + ')';
  102. };
  103. video.addEventListener('timeupdate', timeupdateListener);
  104.  
  105. progressListener = () => {
  106. if (!player.classList.contains('ytp-autohide') || !video.buffered.length)
  107. return;
  108.  
  109. let buff = video.buffered.end(video.buffered.length - 1);
  110.  
  111. for (let i = 0; i < chars.length; i++) {
  112. let ts = chars[i];
  113. if (ts < buff || !capduration) {
  114. cap = i;
  115. capstart = ts;
  116. capduration = ((chars[i + 1] ? chars[i + 1] : video.duration) - ts);
  117. } else {
  118. break;
  119. }
  120. }
  121.  
  122. if (cap > lastusedcapbuf)
  123. loadbars[lastusedcapbuf].style.transform = 'scaleX(1)';
  124.  
  125. lastusedcapbuf = cap;
  126.  
  127. loadbars[cap].style.transform = 'scaleX(' + ((buff - capstart) / capduration) + ')';
  128. };
  129. video.addEventListener('progress', progressListener);
  130. eventHandlers = [video, timeupdateListener, progressListener];
  131. } else {
  132. timeupdateListener = function () {
  133. if (player.classList.contains('ytp-autohide'))
  134. progressbars[0].style.transform = 'scaleX(' + (video.currentTime / video.duration) + ')';
  135. };
  136. video.addEventListener('timeupdate', timeupdateListener);
  137.  
  138. progressListener = function () {
  139. if (player.classList.contains('ytp-autohide') && video.buffered.length)
  140. loadbars[0].style.transform = 'scaleX(' + (video.buffered.end(video.buffered.length - 1) / video.duration) + ')';
  141. };
  142. video.addEventListener('progress', progressListener);
  143. eventHandlers = [video, timeupdateListener, progressListener];
  144. }
  145. }