自动开启B站视频字幕功能
目前為
// ==UserScript==
// @name 自动打开b站字幕
// @namespace http://tampermonkey.net/
// @version 1.0.3
// @description 自动开启B站视频字幕功能
// @author NuperAki
// @match https://www.bilibili.com/video/*
// @icon https://www.bilibili.com/favicon.ico
// @grant none
// @license MIT License
// @supportURL https://github.com/TheHeartFickle/OpenSubtitleOnBiliBili/issues
// ==/UserScript==
(function () {
let subtitleInterval = null;
let currentHref = window.location.href;
// 字幕开启状态的d值特征
const ACTIVE_D_PATTERN = /M40,-30/;
// 查找字幕按钮
function findSubtitle() {
const buttons = document.querySelectorAll('.bpx-common-svg-icon');
for (const btn of buttons) {
const parent = btn.parentElement?.parentElement;
if (parent?.getAttribute('aria-label') === '字幕') {
return btn;
}
}
return null;
}
// 检查字幕按钮是否已激活
function isSubtitleActive(btn) {
const maskPath = btn.querySelector('mask path');
if (!maskPath) return false;
// 检测d属性值
const dValue = maskPath.getAttribute('d') || '';
return ACTIVE_D_PATTERN.test(dValue);
}
function tryOpenSubtitle() {
const btn = findSubtitle();
if (!btn) return false;
// 检查字幕状态
const isActive = isSubtitleActive(btn);
if (!isActive) {
btn.click();
console.log("B站字幕已自动开启");
return true;
}
return false;
}
function openSubtitle() {
// 清除现有定时器
if (subtitleInterval) {
clearInterval(subtitleInterval);
subtitleInterval = null;
}
// 立即尝试打开字幕
if (tryOpenSubtitle()) return;
// 设置定时器定期检查
subtitleInterval = setInterval(() => {
if (tryOpenSubtitle()) {
clearInterval(subtitleInterval);
subtitleInterval = null;
}
}, 500);
// 10秒后自动停止检测
setTimeout(() => {
if (subtitleInterval) {
clearInterval(subtitleInterval);
subtitleInterval = null;
}
}, 10000);
}
// 初始检测
openSubtitle();
// 监听URL变化(SPA路由切换)
setInterval(() => {
if (window.location.href !== currentHref) {
currentHref = window.location.href;
openSubtitle();
}
}, 500);
// 页面完全加载后重新检测
window.addEventListener('load', openSubtitle);
// 监听播放器状态变化
const playerContainer = document.querySelector('.bpx-player-container, #bilibili-player');
if (playerContainer) {
const observer = new MutationObserver(optimizedObserverCallback);
observer.observe(playerContainer, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
}
})();