- // ==UserScript==
- // @name 哔哩哔哩(bilibili)播放器辅助设置
- // @namespace bilibili
- // @version 1.0.1
- // @description B站播放器增强设置,自动宽屏,默认最高画质,默认关闭弹幕等
- // @author darkless
- // @match https://www.bilibili.com/video/*
- // @grant none
- // ==/UserScript==
-
- 'use strict';
-
- (async function () {
- console.group('哔哩哔哩(bilibili)播放器初始化开始');
- const config = {
- closeBarrage: true, // true表示关闭弹幕,false表示开启弹幕
- autoWidescreen: true, // true表示开启自动宽屏,false表示关闭自动宽屏
- autoPlayList: [], // 开启自动连播白名单,目前仅支持BV号,如 ['BV123445']
- redundantElements: [
- '#bannerAd',
- '#activity_vote', /* */
- '.ad-report', /* */
- '.video-page-special-card',
- 'reportFirst1',
- 'reportFirst2',
- 'reportFirst3',
- ],
- };
-
- const document = this.document;
-
- const handleSettingLoaded = (e) => {
- console.log('加载播放器设置');
- const videoControl = e.detail.videoControl;
- const videoSendBar = e.detail.videoSendBar;
-
- // 切换弹幕开关
- switchBarrage(config.closeBarrage, videoSendBar);
-
- // 最高画质
- hightQuality(videoControl);
-
- // 自动宽屏
- autoWidescreen(config.autoWidescreen, videoControl);
-
- // 自动播放列表
- autoPlayList(config.autoPlayList, this);
-
- // 展开简介
- expandDescription(document);
-
- // 删除部分元素
- removeElements(config.redundantElements, document);
-
- console.log('初始化结束');
- console.groupEnd();
- };
-
- const handlePlayerLoaded = (e) => {
- const { data } = e;
- if (data.type === 'PlayerLoaded' || data.type === 'VideoLoaded') {
- console.log(data)
- getRoots(document);
- }
- };
-
- document.addEventListener('SettingLoaded', handleSettingLoaded);
- this.addEventListener('message', handlePlayerLoaded);
-
- observePlayerStatus(this);
- }.bind(window)());
-
- function removeElements(selectors, document) {
-
- selectors.forEach((selector) => {
- let elements;
- if (selector.indexOf('.') === 0) {
- elements = document.querySelectorAll(selector);
- } else {
- elements = document.querySelector(selector);
- }
-
- if (elements && Array.isArray(elements)) {
- elements.forEach((element) => {
- if (typeof element.remove === 'function') {
- element.remove();
- }
- });
- } else {
- if (typeof elements.remove === 'function') {
- elements.remove();
- }
- }
- });
- console.log('部分推广元素已删除');
- }
-
- function expandDescription(document) {
- const element = document.getElementsByClassName('desc-info')[0];
- if (!/open/.test(element.className)) {
- document.getElementsByClassName('toggle-btn')[0].click();
- }
- console.log('简介已展开');
- }
-
- function autoPlayList(videos, window) {
- const button = window.document.getElementsByClassName('switch-button').item(0);
- const bv = window.location.pathname.split('/')[2];
- const isAutoPlayVideo = videos.includes(bv);
- let timer;
-
- let isOpen = button.className === 'switch-button on';
- let needOpen = !isOpen && isAutoPlayVideo;
- let needClose = isOpen && !isAutoPlayVideo;
-
- const observer = new window.MutationObserver((_, observer) => {
- clearTimeout(timer);
- isOpen = button.className === 'switch-button on';
- needOpen = needOpen = !isOpen && isAutoPlayVideo;
- needClose = isOpen && !isAutoPlayVideo;
-
- if (!needOpen && !needClose) {
- observer.disconnect();
- console.log('自动连P已切换');
- return;
- }
-
- if (needOpen || needClose) {
- timer = setTimeout(() => {
- button.click();
- }, 3000);
- return;
- }
- });
-
- observer.observe(button, {
- attributes: true,
- attributeFilter: ['class'],
- attributeOldValue: true,
- });
-
- if (needOpen || needClose) {
- timer = setTimeout(() => button.click(), 0);
- }
- }
-
- function autoWidescreen(autoWidescreen, element) {
- const widescreenElement = element.getElementsByClassName('bilibili-player-video-btn-widescreen').item(0);
- if (autoWidescreen && !/closed/.test(widescreenElement.className)) {
- widescreenElement.click();
- console.log('已开启宽屏');
- }
- }
-
- function hightQuality(element) {
- const isVip = document.querySelector('.profile-info .vip') !== null;
- const isLogin = document.getElementById('bilibiliPlayer').getAttribute('data-login') === 'true';
-
- const list = element.querySelectorAll('.bilibili-player-video-btn-quality .bui-select-list .bui-select-item');
- const newList = Array.prototype.slice.call(list);
- newList.some((item) => {
- let result = true;
-
- const children = item.children;
- if (children.length >= 3) {
- const className = children.item(2).className;
- switch (className) {
- case 'bilibili-player-bigvip':
- result = isVip;
- break;
- case 'bilibili-player-needlogin':
- result = isLogin;
- break;
- default:
- result = true;
- break;
- }
- }
-
- if (result) {
- console.log('画质已切换至最高');
- item.click();
- }
- return result;
- });
- }
-
- function switchBarrage(close, root) {
- const element = root.getElementsByClassName('bui-switch-input').item(0);
-
- if (close === element.checked) {
- element.click();
- }
- console.log('弹幕开关已切换');
- }
-
- function getRoots(document) {
- const videoControls = document.getElementsByClassName('bilibili-player-video-control');
- const videoSendBars = document.getElementsByClassName('bilibili-player-video-sendbar');
-
- if (videoControls.length > 0 && videoSendBars.length > 0) {
- document.dispatchEvent(new CustomEvent('SettingLoaded', {
- detail: {
- videoControl: videoControls[0],
- videoSendBar: videoSendBars[0],
- },
- }));
- } else {
- setTimeout(() => {
- getRoots(document);
- }, 500);
- }
- }
-
- function observePlayerStatus(window) {
- const rootElement = window.document.getElementById('bilibiliPlayer');
- const videoElement = rootElement.getElementsByClassName('bilibili-player-video')[0].children[0];
-
- const rootObserver = new window.MutationObserver((_, observer) => {
- window.postMessage({
- type: 'PlayerLoaded',
- timestamp: Date.now(),
- }, '*');
- observer.disconnect();
- });
-
- rootObserver.observe(rootElement, {
- attributes: true,
- attributeFilter: ['data-login'],
- childList: true,
- });
-
- const videoObserver = new window.MutationObserver(() => {
- setTimeout(() => {
- window.postMessage({
- type: 'VideoLoaded',
- timestamp: Date.now(),
- }, '*');
- }, 3000);
- });
-
- videoObserver.observe(videoElement, {
- attributes: true,
- attributeFilter: ['src'],
- });
- }