Greasy Fork 支持简体中文。

YouTube Volume Control with Memory and Draggable UI

Set YouTube volume manually on a scale of 1-100, remember last set volume, and inject the UI to the left of the volume slider on the video player. Syncs the slider, disables invalid inputs, and adds debugging.

目前為 2024-10-24 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name YouTube Volume Control with Memory and Draggable UI
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.6
  5. // @description Set YouTube volume manually on a scale of 1-100, remember last set volume, and inject the UI to the left of the volume slider on the video player. Syncs the slider, disables invalid inputs, and adds debugging.
  6. // @author Nick2bad4u
  7. // @match *://www.youtube.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  9. // @grant none
  10. // @license UnLicense
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Variable to hold the previous volume level
  17. let previousVolume = localStorage.getItem('youtubeVolume') || 50;
  18.  
  19. // Create input element for volume control
  20. const volumeInput = document.createElement('input');
  21. volumeInput.type = 'number';
  22. volumeInput.min = 0;
  23. volumeInput.max = 100;
  24. volumeInput.value = previousVolume;
  25.  
  26. // Set input field styles to resemble YouTube's UI
  27. volumeInput.style.width = '30px';
  28. volumeInput.style.marginRight = '10px';
  29. volumeInput.style.backgroundColor = 'rgba(255, 255, 255, 0.0)';
  30. volumeInput.style.color = 'white'; // Change text color to white
  31. volumeInput.style.border = '0px solid rgba(255, 255, 255, 0.0)';
  32. volumeInput.style.borderRadius = '4px';
  33. volumeInput.style.zIndex = 9999;
  34. volumeInput.style.height = '24px';
  35. volumeInput.style.fontSize = '16px';
  36. volumeInput.style.padding = '0 4px';
  37. volumeInput.style.transition = 'border-color 0.3s, background-color 0.3s'; // Added background color transition
  38. volumeInput.style.outline = 'none';
  39. volumeInput.style.position = 'relative';
  40. volumeInput.style.top = '13px'; // Adjust to lower the input 13 pixels
  41.  
  42. // Change border color on focus
  43. volumeInput.addEventListener('focus', () => {
  44. volumeInput.style.borderColor = 'rgba(255, 255, 255, 0.6)';
  45. });
  46.  
  47. volumeInput.addEventListener('blur', () => {
  48. volumeInput.style.borderColor = 'rgba(255, 255, 255, 0.3)';
  49. });
  50.  
  51. // Change background color on hover
  52. volumeInput.addEventListener('mouseenter', () => {
  53. volumeInput.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; // Dark background on hover
  54. });
  55.  
  56. volumeInput.addEventListener('mouseleave', () => {
  57. volumeInput.style.backgroundColor = 'rgba(255, 255, 255, 0.0)'; // Restore background when not hovered
  58. });
  59.  
  60. // Prevent YouTube hotkeys when typing in the input
  61. volumeInput.addEventListener('keydown', function(event) {
  62. event.stopPropagation();
  63. console.log('Keydown event in volume input, stopping propagation.');
  64. });
  65.  
  66. // Function to set the volume based on input value
  67. function setVolume() {
  68. const player = document.querySelector('video');
  69. if (player) {
  70. let volumeValue = volumeInput.value;
  71.  
  72. // Validate input (must be between 0 and 100)
  73. if (volumeValue < 0) volumeValue = 0;
  74. if (volumeValue > 100) volumeValue = 100;
  75. volumeInput.value = volumeValue;
  76.  
  77. // Set the player volume and save to local storage
  78. player.volume = volumeValue / 100;
  79. localStorage.setItem('youtubeVolume', volumeValue);
  80. console.log(`Volume set to ${volumeValue} and saved to local storage.`);
  81.  
  82. // Sync YouTube's volume slider UI
  83. const volumeSlider = document.querySelector('.ytp-volume-slider-handle');
  84. if (volumeSlider) {
  85. volumeSlider.style.left = `${volumeValue}%`;
  86. console.log('YouTube volume slider updated.');
  87. }
  88. }
  89. }
  90.  
  91. // Event listener for input change (manually changing the volume in the input box)
  92. volumeInput.addEventListener('input', setVolume);
  93.  
  94. // Function to update the input field when YouTube's player volume is changed
  95. function updateVolumeInput() {
  96. const player = document.querySelector('video');
  97. if (player) {
  98. const currentVolume = Math.round(player.volume * 100);
  99. volumeInput.value = currentVolume;
  100. localStorage.setItem('youtubeVolume', currentVolume);
  101. console.log(`Volume input updated to ${currentVolume} from video player.`);
  102.  
  103. // Show 0 if the video is muted
  104. if (player.muted) {
  105. volumeInput.value = 0;
  106. }
  107. }
  108. }
  109.  
  110. // Function to handle mute changes
  111. function handleMuteChange() {
  112. const player = document.querySelector('video');
  113. if (player) {
  114. if (player.muted) {
  115. volumeInput.value = 0; // Show 0 when muted
  116. } else {
  117. volumeInput.value = previousVolume; // Restore previous volume when unmuted
  118. player.volume = previousVolume / 100; // Set the player volume back to previous
  119. }
  120. console.log(`Mute state changed: muted = ${player.muted}`);
  121. }
  122. }
  123.  
  124. // Inject the input box into YouTube's control bar
  125. function injectVolumeControl() {
  126. const volumeSliderPanel = document.querySelector('.ytp-volume-panel');
  127. if (volumeSliderPanel) {
  128. volumeSliderPanel.parentNode.insertBefore(volumeInput, volumeSliderPanel);
  129. setVolume(); // Set initial volume
  130. const player = document.querySelector('video');
  131. if (player) {
  132. player.addEventListener('volumechange', updateVolumeInput);
  133. player.addEventListener('mute', handleMuteChange);
  134. player.addEventListener('unmute', handleMuteChange);
  135. console.log('Volume input injected and event listeners attached.');
  136. }
  137. } else {
  138. console.log('Volume panel not found, retrying...');
  139. setTimeout(injectVolumeControl, 500);
  140. }
  141. }
  142.  
  143. // Inject the volume control when the page is ready
  144. injectVolumeControl();
  145.  
  146. })();