哔哩哔哩(bilibili)播放器辅助设置

B站播放器增强设置,自动宽屏,默认最高画质,默认关闭弹幕等

  1. // ==UserScript==
  2. // @name 哔哩哔哩(bilibili)播放器辅助设置
  3. // @namespace bilibili
  4. // @version 1.0.1
  5. // @description B站播放器增强设置,自动宽屏,默认最高画质,默认关闭弹幕等
  6. // @author darkless
  7. // @match https://www.bilibili.com/video/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. 'use strict';
  12.  
  13. (async function () {
  14. console.group('哔哩哔哩(bilibili)播放器初始化开始');
  15. const config = {
  16. closeBarrage: true, // true表示关闭弹幕,false表示开启弹幕
  17. autoWidescreen: true, // true表示开启自动宽屏,false表示关闭自动宽屏
  18. autoPlayList: [], // 开启自动连播白名单,目前仅支持BV号,如 ['BV123445']
  19. redundantElements: [
  20. '#bannerAd',
  21. '#activity_vote', /* */
  22. '.ad-report', /* */
  23. '.video-page-special-card',
  24. 'reportFirst1',
  25. 'reportFirst2',
  26. 'reportFirst3',
  27. ],
  28. };
  29.  
  30. const document = this.document;
  31.  
  32. const handleSettingLoaded = (e) => {
  33. console.log('加载播放器设置');
  34. const videoControl = e.detail.videoControl;
  35. const videoSendBar = e.detail.videoSendBar;
  36.  
  37. // 切换弹幕开关
  38. switchBarrage(config.closeBarrage, videoSendBar);
  39.  
  40. // 最高画质
  41. hightQuality(videoControl);
  42.  
  43. // 自动宽屏
  44. autoWidescreen(config.autoWidescreen, videoControl);
  45.  
  46. // 自动播放列表
  47. autoPlayList(config.autoPlayList, this);
  48.  
  49. // 展开简介
  50. expandDescription(document);
  51.  
  52. // 删除部分元素
  53. removeElements(config.redundantElements, document);
  54.  
  55. console.log('初始化结束');
  56. console.groupEnd();
  57. };
  58.  
  59. const handlePlayerLoaded = (e) => {
  60. const { data } = e;
  61. if (data.type === 'PlayerLoaded' || data.type === 'VideoLoaded') {
  62. console.log(data)
  63. getRoots(document);
  64. }
  65. };
  66.  
  67. document.addEventListener('SettingLoaded', handleSettingLoaded);
  68. this.addEventListener('message', handlePlayerLoaded);
  69.  
  70. observePlayerStatus(this);
  71. }.bind(window)());
  72.  
  73. function removeElements(selectors, document) {
  74.  
  75. selectors.forEach((selector) => {
  76. let elements;
  77. if (selector.indexOf('.') === 0) {
  78. elements = document.querySelectorAll(selector);
  79. } else {
  80. elements = document.querySelector(selector);
  81. }
  82.  
  83. if (elements && Array.isArray(elements)) {
  84. elements.forEach((element) => {
  85. if (typeof element.remove === 'function') {
  86. element.remove();
  87. }
  88. });
  89. } else {
  90. if (typeof elements.remove === 'function') {
  91. elements.remove();
  92. }
  93. }
  94. });
  95. console.log('部分推广元素已删除');
  96. }
  97.  
  98. function expandDescription(document) {
  99. const element = document.getElementsByClassName('desc-info')[0];
  100. if (!/open/.test(element.className)) {
  101. document.getElementsByClassName('toggle-btn')[0].click();
  102. }
  103. console.log('简介已展开');
  104. }
  105.  
  106. function autoPlayList(videos, window) {
  107. const button = window.document.getElementsByClassName('switch-button').item(0);
  108. const bv = window.location.pathname.split('/')[2];
  109. const isAutoPlayVideo = videos.includes(bv);
  110. let timer;
  111.  
  112. let isOpen = button.className === 'switch-button on';
  113. let needOpen = !isOpen && isAutoPlayVideo;
  114. let needClose = isOpen && !isAutoPlayVideo;
  115.  
  116. const observer = new window.MutationObserver((_, observer) => {
  117. clearTimeout(timer);
  118. isOpen = button.className === 'switch-button on';
  119. needOpen = needOpen = !isOpen && isAutoPlayVideo;
  120. needClose = isOpen && !isAutoPlayVideo;
  121.  
  122. if (!needOpen && !needClose) {
  123. observer.disconnect();
  124. console.log('自动连P已切换');
  125. return;
  126. }
  127.  
  128. if (needOpen || needClose) {
  129. timer = setTimeout(() => {
  130. button.click();
  131. }, 3000);
  132. return;
  133. }
  134. });
  135.  
  136. observer.observe(button, {
  137. attributes: true,
  138. attributeFilter: ['class'],
  139. attributeOldValue: true,
  140. });
  141.  
  142. if (needOpen || needClose) {
  143. timer = setTimeout(() => button.click(), 0);
  144. }
  145. }
  146.  
  147. function autoWidescreen(autoWidescreen, element) {
  148. const widescreenElement = element.getElementsByClassName('bilibili-player-video-btn-widescreen').item(0);
  149. if (autoWidescreen && !/closed/.test(widescreenElement.className)) {
  150. widescreenElement.click();
  151. console.log('已开启宽屏');
  152. }
  153. }
  154.  
  155. function hightQuality(element) {
  156. const isVip = document.querySelector('.profile-info .vip') !== null;
  157. const isLogin = document.getElementById('bilibiliPlayer').getAttribute('data-login') === 'true';
  158.  
  159. const list = element.querySelectorAll('.bilibili-player-video-btn-quality .bui-select-list .bui-select-item');
  160. const newList = Array.prototype.slice.call(list);
  161. newList.some((item) => {
  162. let result = true;
  163.  
  164. const children = item.children;
  165. if (children.length >= 3) {
  166. const className = children.item(2).className;
  167. switch (className) {
  168. case 'bilibili-player-bigvip':
  169. result = isVip;
  170. break;
  171. case 'bilibili-player-needlogin':
  172. result = isLogin;
  173. break;
  174. default:
  175. result = true;
  176. break;
  177. }
  178. }
  179.  
  180. if (result) {
  181. console.log('画质已切换至最高');
  182. item.click();
  183. }
  184. return result;
  185. });
  186. }
  187.  
  188. function switchBarrage(close, root) {
  189. const element = root.getElementsByClassName('bui-switch-input').item(0);
  190.  
  191. if (close === element.checked) {
  192. element.click();
  193. }
  194. console.log('弹幕开关已切换');
  195. }
  196.  
  197. function getRoots(document) {
  198. const videoControls = document.getElementsByClassName('bilibili-player-video-control');
  199. const videoSendBars = document.getElementsByClassName('bilibili-player-video-sendbar');
  200.  
  201. if (videoControls.length > 0 && videoSendBars.length > 0) {
  202. document.dispatchEvent(new CustomEvent('SettingLoaded', {
  203. detail: {
  204. videoControl: videoControls[0],
  205. videoSendBar: videoSendBars[0],
  206. },
  207. }));
  208. } else {
  209. setTimeout(() => {
  210. getRoots(document);
  211. }, 500);
  212. }
  213. }
  214.  
  215. function observePlayerStatus(window) {
  216. const rootElement = window.document.getElementById('bilibiliPlayer');
  217. const videoElement = rootElement.getElementsByClassName('bilibili-player-video')[0].children[0];
  218.  
  219. const rootObserver = new window.MutationObserver((_, observer) => {
  220. window.postMessage({
  221. type: 'PlayerLoaded',
  222. timestamp: Date.now(),
  223. }, '*');
  224. observer.disconnect();
  225. });
  226.  
  227. rootObserver.observe(rootElement, {
  228. attributes: true,
  229. attributeFilter: ['data-login'],
  230. childList: true,
  231. });
  232.  
  233. const videoObserver = new window.MutationObserver(() => {
  234. setTimeout(() => {
  235. window.postMessage({
  236. type: 'VideoLoaded',
  237. timestamp: Date.now(),
  238. }, '*');
  239. }, 3000);
  240. });
  241.  
  242. videoObserver.observe(videoElement, {
  243. attributes: true,
  244. attributeFilter: ['src'],
  245. });
  246. }

QingJ © 2025

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