YouTube Middle Mouse Button Mute / Unmute

Mutes / unmutes a YouTube video / Shorts by clicking the middle mouse button within the video player. For Shorts you can also middle mouse click the black side bars around the video. While performing the middle mouse button click, the scroll button gets disabled. Mute / unmute / scroll disabling won't work with any elements floating over the video player.

  1. // ==UserScript==
  2. // @name YouTube Middle Mouse Button Mute / Unmute
  3. // @description Mutes / unmutes a YouTube video / Shorts by clicking the middle mouse button within the video player. For Shorts you can also middle mouse click the black side bars around the video. While performing the middle mouse button click, the scroll button gets disabled. Mute / unmute / scroll disabling won't work with any elements floating over the video player.
  4. // @namespace https://gf.qytechs.cn/users/877912
  5. // @version 0.5
  6. // @license MIT
  7. // @match *://*.youtube.com/watch*?*v=*
  8. // @match *://*.youtube.com/embed/*?*v=*
  9. // @match *://*.youtube.com/v/*
  10. // @match *://*.youtube.com/shorts/*
  11. // @run-at document-start
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function() {
  16.  
  17. // Flag to enable or disable showing borders around floating elements aka ignoredMuteUnmuteElements and debug elements
  18. const debug = false;
  19.  
  20. const muteUnmuteElements = {
  21. videoAreaRegularAndShorts: "video.video-stream.html5-main-video",
  22. videoAreaRegularBlackBars1: "div.ytp-player-content.ytp-iv-player-content[data-layer='4']",
  23. videoAreaRegularBlackBars2: "div#movie_player",
  24. videoAreaShortsBlackBars: "div#shorts-container",
  25. muteButtonRegular: "button.ytp-mute-button",
  26. muteButtonShorts: "button.YtdDesktopShortsVolumeControlsMuteIconButton",
  27. contentContainer: "div#contentContainer",
  28. endscreenPreviousButton: "button.ytp-button.ytp-endscreen-previous",
  29. endscreenNextButton: "button.ytp-button.ytp-endscreen-next",
  30. endscreenContainer: "div.html5-endscreen.ytp-player-content.videowall-endscreen.ytp-show-tiles.ytp-endscreen-paginate",
  31. endscreenContainerVariant1: "div.html5-endscreen.ytp-player-content.videowall-endscreen.ytp-show-tiles",
  32. endscreenContainerVariant2: "div.html5-endscreen.ytp-player-content.videowall-endscreen.ytp-show-tiles[data-layer='4']",
  33. videoOverlay: "div.ytp-iv-video-content[data-layer='4']"
  34. };
  35.  
  36. const ignoredMuteUnmuteElements = {
  37. ".branding-context-container-outer": "blue" // Branding container
  38. };
  39.  
  40. const debugElements = {
  41. ".ytp-cards-teaser": "red", // Cards teaser
  42. ".ytp-pip-button": "red", // Picture-in-Picture button
  43. ".ytp-ad-overlay-container": "red", // Ad overlays
  44. ".ytp-ad-player-overlay": "red", // Ad overlays
  45. ".ytp-endscreen-content": "red", // Endscreen content
  46. ".ytp-chrome-bottom": "red", // Bottom controls (progress bar, play button, etc.)
  47. ".ytp-chrome-top": "red", // Top controls (settings, subtitles, etc.)
  48. ".ytp-gradient-top": "red", // Gradient overlays at the top
  49. ".ytp-gradient-bottom": "red", // Gradient overlays at the bottom
  50. ".ytp-ce-element": "red", // End screen elements
  51. ".ytp-ce-element-shadow": "red", // Shadows for end screen elements
  52. ".ytp-subtitles-button": "red", // Subtitles button
  53. ".ytp-caption-window": "red", // Caption window for subtitles
  54. ".ytp-spinner": "red", // Loading spinner
  55. ".ytp-fullscreen-button": "red", // Fullscreen button
  56. ".ytp-play-button": "red", // Play button
  57. ".ytp-volume-panel": "red", // Volume panel
  58. ".ytp-share-button": "red", // Share button
  59. ".ytp-like-button-renderer": "red", // Like button
  60. ".picture-in-picture-toggle": "red", // Firefox Picture-in-Picture toggle button
  61. ".ytp-title": "red" // YouTube video title area
  62. };
  63.  
  64. let isClicked = false;
  65.  
  66. function handleMiddleClick(event) {
  67. if (event.button !== 1 || isClicked) return;
  68.  
  69. for (let selector of Object.keys(ignoredMuteUnmuteElements)) {
  70. if (event.target.closest(selector) && !event.target.closest(muteUnmuteElements.ytpTitle) && !event.target.closest(muteUnmuteElements.contentContainer)) return;
  71. }
  72.  
  73. let muteButton = null;
  74. isClicked = true;
  75. setTimeout(() => isClicked = false, 200);
  76. event.preventDefault();
  77.  
  78. if (event.target.matches(muteUnmuteElements.videoAreaRegularAndShorts) ||
  79. event.target.matches(muteUnmuteElements.videoOverlay)) {
  80. muteButton = window.location.href.includes("shorts") ? document.querySelector(muteUnmuteElements.muteButtonShorts) : document.querySelector(muteUnmuteElements.muteButtonRegular);
  81. } else if (
  82. event.target.closest(muteUnmuteElements.videoAreaRegularBlackBars1) ||
  83. event.target.matches(muteUnmuteElements.videoAreaRegularBlackBars2) ||
  84. event.target.matches(muteUnmuteElements.contentContainer) ||
  85. event.target.matches(muteUnmuteElements.endscreenPreviousButton) ||
  86. event.target.matches(muteUnmuteElements.endscreenNextButton) ||
  87. event.target.matches(muteUnmuteElements.endscreenContainer) ||
  88. event.target.matches(muteUnmuteElements.endscreenContainerVariant1) ||
  89. event.target.matches(muteUnmuteElements.endscreenContainerVariant2)
  90. ) {
  91. muteButton = document.querySelector(muteUnmuteElements.muteButtonRegular);
  92. } else if (event.target.matches(muteUnmuteElements.videoAreaShortsBlackBars)) {
  93. muteButton = document.querySelector(muteUnmuteElements.muteButtonShorts);
  94. }
  95.  
  96. if (muteButton) muteButton.click();
  97. }
  98.  
  99. function addBorderStyles(elements) {
  100. const style = document.createElement('style');
  101. style.type = 'text/css';
  102. let styles = '';
  103.  
  104. for (let selector in elements) {
  105. styles += `
  106. ${selector} {
  107. border: 2px solid ${elements[selector]} !important;
  108. }
  109. `;
  110. }
  111.  
  112. style.innerHTML = styles;
  113. document.head.appendChild(style);
  114. }
  115.  
  116. document.addEventListener('mousedown', (event) => {
  117. if (event.button === 1) {
  118. if (event.target.matches(muteUnmuteElements.videoAreaRegularAndShorts) ||
  119. event.target.matches(muteUnmuteElements.videoOverlay) ||
  120. event.target.closest(muteUnmuteElements.videoAreaRegularBlackBars1) ||
  121. event.target.matches(muteUnmuteElements.videoAreaRegularBlackBars2) ||
  122. event.target.matches(muteUnmuteElements.videoAreaShortsBlackBars) ||
  123. event.target.matches(muteUnmuteElements.contentContainer) ||
  124. event.target.matches(muteUnmuteElements.endscreenPreviousButton) ||
  125. event.target.matches(muteUnmuteElements.endscreenNextButton) ||
  126. event.target.matches(muteUnmuteElements.endscreenContainer) ||
  127. event.target.matches(muteUnmuteElements.endscreenContainerVariant1) ||
  128. event.target.matches(muteUnmuteElements.endscreenContainerVariant2)) {
  129. handleMiddleClick(event);
  130. }
  131. }
  132. }, true);
  133.  
  134. function waitForKeyElements(selector, actionFunction) {
  135. const observer = new MutationObserver((mutationsList) => {
  136. for (const mutation of mutationsList) {
  137. if (mutation.type === 'childList' && mutation.addedNodes.length) {
  138. mutation.addedNodes.forEach((node) => {
  139. if (node.matches && node.matches(selector)) {
  140. actionFunction(node);
  141. }
  142. });
  143. }
  144. }
  145. });
  146.  
  147. observer.observe(document, { childList: true, subtree: true });
  148. }
  149.  
  150. waitForKeyElements(Object.values(muteUnmuteElements).join(", "), (node) => {
  151. if (node.closest(muteUnmuteElements.videoAreaRegularBlackBars2) || node.matches(muteUnmuteElements.videoAreaShortsBlackBars)) {
  152. node.addEventListener('mousedown', handleMiddleClick, true);
  153. }
  154. });
  155.  
  156. if (debug) {
  157. addBorderStyles(ignoredMuteUnmuteElements);
  158. addBorderStyles(debugElements);
  159. }
  160.  
  161. })();

QingJ © 2025

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