YouTube - Remaining time

Displays the remaining duration of a YouTube video next to the video duration, taking into account the playback rate.

当前为 2023-10-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube - Remaining time
  3. // @namespace https://gist.github.com/4lrick/cf14cf267684f06c1b7bc559ddf2b943
  4. // @version 1.1
  5. // @description Displays the remaining duration of a YouTube video next to the video duration, taking into account the playback rate.
  6. // @description:fr Affiche la durée restante d'une vidéo YouTube à côté de la durée de la vidéo, en tenant compte de la vitesse de lecture.
  7. // @description:es Muestra la duración restante de un video de YouTube junto a la duración del video, teniendo en cuenta la velocidad de reproducción.
  8. // @description:de Zeigt die verbleibende Dauer eines YouTube-Videos neben der Videodauer an und berücksichtigt dabei die Wiedergabegeschwindigkeit.
  9. // @description:it Mostra la durata rimanente di un video di YouTube accanto alla durata del video, tenendo conto della velocità di riproduzione.
  10. // @description:zh 在视频时长旁边显示YouTube视频的剩余时长,考虑播放速度。
  11. // @author 4lrick
  12. // @match https://www.youtube.com/*
  13. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  14. // @grant none
  15. // @license GPL-3.0-only
  16. // ==/UserScript==
  17.  
  18. (() => {
  19. 'use strict';
  20.  
  21. let timeDisplay;
  22. let videoIsInit = false;
  23. let activeVideoElement = null;
  24. let activeVideoInterval = null;
  25.  
  26. const checkAndMonitorVideoPage = () => {
  27. const newVideoPageActive = window.location.href.startsWith('https://www.youtube.com/watch');
  28. if (newVideoPageActive && !videoIsInit) {
  29. initializeTimeDisplay();
  30. videoIsInit = true;
  31. }
  32. };
  33.  
  34. const initializeTimeDisplay = () => {
  35. timeDisplay = document.createElement('div');
  36. timeDisplay.style.display = 'inline-block';
  37. timeDisplay.style.marginLeft = '10px';
  38. timeDisplay.style.color = '#ddd';
  39.  
  40. const timeDuration = document.querySelector('.ytp-time-duration');
  41. const timeContainer = document.querySelector('.ytp-time-display');
  42. const appContainer = document.querySelector('ytd-app');
  43.  
  44. if (timeDuration && timeContainer) {
  45. timeContainer.appendChild(timeDisplay);
  46. }
  47. setupMutationObserver(appContainer);
  48. };
  49.  
  50. const setupMutationObserver = (appContainer) => {
  51. const observer = new MutationObserver((mutationsList, observer) => {
  52. updateActiveVideo();
  53. });
  54. observer.observe(appContainer, { subtree: true, childList: true });
  55. };
  56.  
  57. const updateActiveVideo = () => {
  58. const isMiniplayerActive = document.querySelector('ytd-app').hasAttribute('miniplayer-is-active');
  59. const videoElement = document.querySelector('video');
  60.  
  61. if (!isMiniplayerActive && videoElement) {
  62. if (activeVideoInterval) {
  63. clearInterval(activeVideoInterval);
  64. }
  65.  
  66. activeVideoElement = videoElement;
  67. updateVideoTime();
  68. activeVideoInterval = setInterval(updateVideoTime, 1000);
  69. } else {
  70. clearInterval(activeVideoInterval);
  71. activeVideoElement = null;
  72. timeDisplay.textContent = '';
  73. }
  74. };
  75.  
  76. const updateVideoTime = () => {
  77. const { currentTime, duration, playbackRate } = activeVideoElement;
  78. const timeRemaining = (duration - currentTime) / playbackRate;
  79.  
  80. const hoursRemaining = Math.floor(timeRemaining / 3600);
  81. const minutesRemaining = Math.floor((timeRemaining % 3600) / 60);
  82. const secondsRemaining = Math.floor(timeRemaining % 60);
  83.  
  84. let formattedTimeRemaining = '';
  85. if (hoursRemaining > 0) {
  86. formattedTimeRemaining += hoursRemaining.toString() + ':';
  87. }
  88. formattedTimeRemaining += minutesRemaining.toString().padStart(2, '0') + ':' + secondsRemaining.toString().padStart(2, '0');
  89.  
  90. timeDisplay.textContent = '(' + formattedTimeRemaining + ')';
  91. };
  92.  
  93. const checkVideoPageActiveInterval = () => {
  94. checkAndMonitorVideoPage();
  95. window.requestAnimationFrame(checkVideoPageActiveInterval);
  96. };
  97.  
  98. checkVideoPageActiveInterval();
  99. })();