多倍速调节+倍速同步+回车全屏+播完退出全屏

按自己的使用习惯用ChatGPT写的脚本,我自己测试过了没啥问题,分享给有同样习惯的小伙伴,以后应该不怎么改了,有自己需求的可以自行更改。

目前為 2023-09-05 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name 多倍速调节+倍速同步+回车全屏+播完退出全屏
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description 按自己的使用习惯用ChatGPT写的脚本,我自己测试过了没啥问题,分享给有同样习惯的小伙伴,以后应该不怎么改了,有自己需求的可以自行更改。
  6. // @author ChatGPT
  7. // @match *://www.bilibili.com/video/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. // 创建音量提示的div元素
  15. var volumeHint = document.createElement('div');
  16. volumeHint.classList.add('bpx-player-volume-hint');
  17. volumeHint.style.display = 'none'; // 初始隐藏
  18.  
  19. // 创建音量提示文本元素
  20. var volumeText = document.createElement('span');
  21. volumeText.classList.add('bpx-player-volume-hint-text');
  22. volumeHint.appendChild(volumeText);
  23.  
  24. // 将音量提示添加到B站播放器容器中
  25. var playerContainer = document.querySelector("#bilibili-player > div > div > div.bpx-player-primary-area > div.bpx-player-video-area");
  26. playerContainer.appendChild(volumeHint);
  27.  
  28. const BILIBILI_PLAYBACKRATE = "bilibili_playbackRate";
  29.  
  30. // 监听视频播放事件
  31. const videoElement = document.querySelector('video');
  32. if (!videoElement) return;
  33.  
  34. // 退出全屏函数
  35. function exitFullscreen() {
  36. if (document.exitFullscreen) {
  37. document.exitFullscreen();
  38. } else if (document.webkitExitFullscreen) {
  39. document.webkitExitFullscreen();
  40. } else if (document.mozCancelFullScreen) {
  41. document.mozCancelFullScreen();
  42. } else if (document.msExitFullscreen) {
  43. document.msExitFullscreen();
  44. }
  45. }
  46.  
  47. function triggerFullScreenButton() {
  48. const fullScreenButton = document.querySelector('.bpx-player-ctrl-btn.bpx-player-ctrl-full');
  49. if (fullScreenButton) {
  50. fullScreenButton.click();
  51. }
  52. }
  53.  
  54. // 监听回车键事件
  55. document.addEventListener('keydown', function(event) {
  56. if (event.key === 'Enter') {
  57. triggerFullScreenButton();
  58. }else if (event.key === 'PageUp' || event.key === '+') {
  59. setVideoPlaybackRate(getSavedPlaybackRate() + 0.5,true);
  60. event.preventDefault();
  61. } else if (event.key === 'PageDown' || event.key === '-') {
  62. setVideoPlaybackRate(getSavedPlaybackRate() - 0.5,true);
  63. event.preventDefault();
  64. }
  65. });
  66.  
  67. videoElement.addEventListener('ended', () => {
  68. // 判断当前是否处于全屏状态
  69. if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {
  70. // 连播状态是否开启,开启状态则不退出
  71. const switchButtonSpan = document.querySelector('.switch-button:not(.on)');
  72. if (switchButtonSpan) {
  73. // 退出全屏
  74. exitFullscreen();
  75. }
  76. }
  77. });
  78.  
  79. // 设置视频倍速
  80. const observer = new MutationObserver(() => {
  81. const menu = document.querySelector('.bpx-player-ctrl-playbackrate-menu');
  82. if (!menu) {
  83. return;
  84. }
  85.  
  86. observer.disconnect();
  87.  
  88. const speeds = [4.0, 3.5, 3.0, 2.5, 2.0, 1.75, 1.5, 1.25, 1.0, 0.75, 0.5];
  89.  
  90. const items = menu.querySelectorAll('.bpx-player-ctrl-playbackrate-menu-item');
  91. items.forEach(item => item.remove());
  92.  
  93. speeds.forEach(speed => {
  94. const item = document.createElement('li');
  95. item.classList.add('bpx-player-ctrl-playbackrate-menu-item');
  96. item.setAttribute('data-value', speed.toString());
  97. item.textContent = speed.toString();
  98. menu.appendChild(item);
  99.  
  100. // 添加点击事件处理程序
  101. item.addEventListener('click', () => {
  102. const selectedSpeed = parseFloat(item.getAttribute('data-value'));
  103. // 将选中的倍速值保存到localStorage
  104. localStorage.setItem(BILIBILI_PLAYBACKRATE, selectedSpeed.toString());
  105.  
  106. // 移除其他项的选中状态,只在点击的项上添加选中状态
  107. items.forEach(otherItem => otherItem.classList.remove('bpx-state-active'));
  108. item.classList.add('bpx-state-active');
  109.  
  110. setVideoPlaybackRate(selectedSpeed); // 设置视频倍速
  111. });
  112. });
  113.  
  114. const defaultSpeed = 1.0;
  115. const savedSpeed = getSavedPlaybackRate();
  116. if (savedSpeed) {
  117. setVideoPlaybackRate(savedSpeed);
  118. const activeItem = menu.querySelector(`.bpx-player-ctrl-playbackrate-menu-item[data-value="${savedSpeed}"]`);
  119. if (activeItem) {
  120. activeItem.classList.add('bpx-state-active');
  121. }
  122. console.log('设置为上次设置的倍速: ', savedSpeed);
  123. } else {
  124. setVideoPlaybackRate(defaultSpeed);
  125. const activeItem = menu.querySelector(`.bpx-player-ctrl-playbackrate-menu-item[data-value="${defaultSpeed}"]`);
  126. if (activeItem) {
  127. activeItem.classList.add('bpx-state-active');
  128. }
  129. console.log('缓存未找到上次设置的倍速,使用默认倍速: ', defaultSpeed);
  130. }
  131.  
  132. });
  133.  
  134. observer.observe(document.documentElement, {
  135. childList: true,
  136. subtree: true
  137. });
  138.  
  139. // 读取localStorage中的倍速值
  140. function getSavedPlaybackRate() {
  141. const savedSpeed = localStorage.getItem(BILIBILI_PLAYBACKRATE);
  142. if (savedSpeed) {
  143. return parseFloat(savedSpeed);
  144. }
  145. return null;
  146. }
  147.  
  148. function formatNumber(number) {
  149. // 判断是否为整数
  150. if (number % 1 === 0) {
  151. return number + '.0';
  152. } else {
  153. return number.toString();
  154. }
  155. }
  156.  
  157. // 定义一个函数来设置视频倍速
  158. function setVideoPlaybackRate(rate,isHint) {
  159. const menu = document.querySelector('.bpx-player-ctrl-playbackrate-menu');
  160. if (!menu) return;
  161.  
  162. const menuItem = menu.querySelector(`.bpx-player-ctrl-playbackrate-menu-item[data-value="${rate}"]`);
  163. if (menuItem) {
  164. menuItem.click(); // Simulate clicking the menu item
  165. }
  166.  
  167. if(isHint){
  168. // 在事件处理程序中设置音量提示文本
  169. var customText = '倍速 ' + formatNumber(getSavedPlaybackRate()); // 替换为您想要的文本
  170. volumeText.textContent = customText;
  171.  
  172. // 显示音量提示
  173. volumeHint.style.display = 'block';
  174.  
  175. // 设置1秒后自动隐藏音量提示
  176. setTimeout(function() {
  177. volumeHint.style.display = 'none';
  178. }, 500); // 1秒后隐藏
  179. }
  180. }
  181.  
  182. })();