YouTube Quick Speed Interface

Modify the YouTube HTML player interface

当前为 2023-07-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Quick Speed Interface
  3. // @name:en YouTube Quick Speed Interface
  4. // @namespace https://twitter.com/CobleeH
  5. // @version 1.10
  6. // @description Modify the YouTube HTML player interface
  7. // @description:en Modify the YouTube HTML player interface
  8. // @author CobleeH
  9. // @match https://www.youtube.com/*
  10. // @grant none
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Add speed options
  18. function addSpeedOptions() {
  19. // Check if speed options are already added
  20. if (document.querySelector('.ytp-speed-options')) {
  21. return;
  22. }
  23.  
  24. var rightControls = document.querySelector('.ytp-right-controls');
  25. var leftControls = document.querySelector('.ytp-left-controls');
  26. if (rightControls && leftControls) {
  27. var speedOptions = document.createElement('div');
  28. speedOptions.classList.add('ytp-speed-options');
  29. speedOptions.style.display = 'flex';
  30. speedOptions.style.alignItems = 'center';
  31. speedOptions.style.order = '2';
  32. speedOptions.style.marginLeft = '10px';
  33. speedOptions.style.marginRight = '25px';
  34.  
  35. var label = document.createElement('span');
  36. label.innerText = 'Speed';
  37. speedOptions.appendChild(label);
  38.  
  39. var speeds = [0.5, 1, 1.5, 2];
  40. speeds.forEach(function(speed) {
  41. var option = document.createElement('div');
  42. option.innerText = speed + 'x';
  43. option.classList.add('ytp-speed-option');
  44. option.style.cursor = 'pointer';
  45. option.style.marginLeft = '5px';
  46. option.addEventListener('click', function() {
  47. var player = document.querySelector('.video-stream');
  48. if (player) {
  49. player.playbackRate = speed;
  50. highlightOption(option);
  51. }
  52. });
  53.  
  54. option.addEventListener('mouseover', function() {
  55. option.classList.add('highlighted');
  56. });
  57.  
  58. option.addEventListener('mouseout', function() {
  59. if (!option.classList.contains('active')) {
  60. option.classList.remove('highlighted');
  61. }
  62. });
  63.  
  64. speedOptions.appendChild(option);
  65. });
  66.  
  67. leftControls.style.order = '1';
  68. rightControls.style.order = '3';
  69.  
  70. document.querySelector('.ytp-chrome-controls').appendChild(speedOptions);
  71. }
  72. }
  73.  
  74. function highlightOption(option) {
  75. // Remove highlight from other options
  76. var options = document.querySelectorAll('.ytp-speed-option');
  77. options.forEach(function(opt) {
  78. opt.classList.remove('active');
  79. });
  80.  
  81. // Add highlight to the current option
  82. option.classList.add('active');
  83. }
  84.  
  85. // Add highlight styles
  86. var style = document.createElement('style');
  87. style.innerHTML = `
  88. .ytp-speed-option {
  89. transition: background-color 0.3s;
  90. }
  91.  
  92. .ytp-speed-option:hover {
  93. background-color: rgba(211, 211, 211, 0.4);
  94. }
  95.  
  96. .ytp-speed-option.active,
  97. .ytp-speed-option.active:hover {
  98. background-color: rgba(211, 211, 211, 0.4);
  99. }
  100. `;
  101. document.head.appendChild(style);
  102.  
  103. // Listen for URL changes and automatically reset speed highlight to 1x
  104. var currentURL = window.location.href;
  105. setInterval(function() {
  106. var newURL = window.location.href;
  107. if (newURL !== currentURL) {
  108. // Reset speed options highlight on URL change
  109. var options = document.querySelectorAll('.ytp-speed-option');
  110. options.forEach(function(opt) {
  111. opt.classList.remove('active');
  112. });
  113. // Set 1x speed option as highlighted
  114. var oneXOption = document.querySelector('.ytp-speed-option:nth-child(3)'); // 1x is at the third position
  115. if (oneXOption) {
  116. oneXOption.classList.add('active');
  117. }
  118. // Update currentURL
  119. currentURL = newURL;
  120. }
  121. }, 500); // Check for URL changes every 0.5 seconds
  122.  
  123. // Use MutationObserver to listen for changes in the player container element
  124. var observer = new MutationObserver(function(mutations) {
  125. mutations.forEach(function(mutation) {
  126. // Check for newly added nodes
  127. if (mutation.addedNodes) {
  128. Array.from(mutation.addedNodes).forEach(function(node) {
  129. if (node.classList && node.classList.contains('html5-video-player')) {
  130. // Add speed options when the player container element changes
  131. addSpeedOptions();
  132. }
  133. });
  134. }
  135. });
  136. });
  137.  
  138. // Observe changes in the entire document
  139. observer.observe(document.documentElement, { childList: true, subtree: true });
  140.  
  141. // Add speed options after the page is fully loaded
  142. document.addEventListener('DOMContentLoaded', function() {
  143. addSpeedOptions();
  144. });
  145. })();