您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
仅在指定UP主的视频下自动开启字幕,并支持设置默认倍速(可选择是否跟随白名单),新增跳过片头片尾功能
// ==UserScript== // @name 哔哩哔哩自动打开字幕+倍速(兼容自动连播,可配置UP主白名单) // @namespace http://tampermonkey.net/ // @version 1.4 // @description 仅在指定UP主的视频下自动开启字幕,并支持设置默认倍速(可选择是否跟随白名单),新增跳过片头片尾功能 // @author Scabish // @match https://www.bilibili.com/video/* // @icon https://www.google.com/s2/favicons?sz=64&domain=bilibili.com // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (function() { 'use strict'; let currentVideoId = ''; // 初始化页面变化观察器 function initUrlObserver() { // 监听URL变化(History API) const pushState = history.pushState; history.pushState = function() { pushState.apply(this, arguments); checkForVideoChange(); }; const replaceState = history.replaceState; history.replaceState = function() { replaceState.apply(this, arguments); checkForVideoChange(); }; window.addEventListener('popstate', checkForVideoChange); // 初始检查 checkForVideoChange(); } // 检查视频是否变化 function checkForVideoChange() { const newVideoId = getBilibiliVideoIdFromUrlRegex(); if (newVideoId && newVideoId !== currentVideoId) { currentVideoId = newVideoId; handlePage(); } } // 从URL获取视频ID function getBilibiliVideoIdFromUrlRegex() { const url = window.location.href; const regex = /https:\/\/www\.bilibili\.com\/video\/(BV[a-zA-Z0-9]+)/; const match = url.match(regex); return (match && match[1]) || null; } // 处理页面逻辑 async function handlePage() { console.log("[字幕脚本] 检测到新视频,开始处理..."); // 等待视频播放器加载完成 await waitForElm('.bpx-player-container'); // 等待UP主信息加载 const upName = await getUpName(); if (!upName) { console.log("[字幕脚本] 未获取到UP主信息"); return; } const whitelist = getWhitelist(); const onlyWhitelistForSpeed = getOnlyWhitelistForSpeed(); const skipIntroOutro = getSkipIntroOutro(); console.log("[字幕脚本] 当前UP主:", upName, " 白名单:", whitelist, " 倍速跟随白名单:", onlyWhitelistForSpeed, " 自动跳过片头片尾:", skipIntroOutro); // 处理字幕 if (whitelist.includes(upName)) { openChineseSubtitle(); // 修改为新的字幕打开方式 } // 处理倍速 const speed = getDefaultSpeed(); if (speed) { if (!onlyWhitelistForSpeed || whitelist.includes(upName)) { setPlaybackRate(speed); } } // 处理跳过片头片尾 if (skipIntroOutro) { setupIntroOutroSkipper(); } } // 获取UP主名称(兼容新旧界面) async function getUpName() { // 尝试多种选择器,兼容不同界面 const selectors = [ '.up-name', '.video-author-name', '.user-name' ]; for (const selector of selectors) { const element = await waitForElm(selector, 5000); // 5秒超时 if (element) { return element.textContent.trim(); } } return null; } // 打开中文字幕(修改为点击中文选项的方式) function openChineseSubtitle() { // 多次尝试,确保能找到按钮 const maxAttempts = 8; let attempts = 0; const tryOpenSubtitle = () => { if (attempts >= maxAttempts) { console.log("[字幕脚本] 尝试打开字幕达到最大次数,可能未找到字幕选项"); return; } attempts++; // 首先检查字幕是否已经打开 const subtitleTrack = document.querySelector('.bpx-player-subtitle-track'); if (subtitleTrack && !subtitleTrack.classList.contains('hide')) { console.log("[字幕脚本] 字幕已打开"); return; } // 步骤1: 找到并点击字幕按钮,打开字幕菜单 const subtitleButtons = [ '.bpx-player-ctrl-btn[aria-label="字幕"]', '.sub-btn', '.bpx-player-subtitle-switch' ].map(selector => document.querySelector(selector)); const subtitleButton = subtitleButtons.find(btn => btn !== null); if (subtitleButton) { // 点击字幕按钮打开菜单 subtitleButton.click(); console.log("[字幕脚本] 已点击字幕按钮,打开菜单"); // 步骤2: 等待并点击"中文"字幕选项 setTimeout(() => { const chineseSubtitle = document.querySelector('.bpx-player-ctrl-subtitle-language-item-text'); if (chineseSubtitle && chineseSubtitle.textContent.trim() === "中文") { chineseSubtitle.click(); console.log("[字幕脚本] 已点击中文选项,打开字幕"); } else { console.log("[字幕脚本] 未找到中文选项,将重试"); // 关闭字幕菜单 subtitleButton.click(); setTimeout(tryOpenSubtitle, 1000); } }, 500); // 等待菜单展开 } else { console.log("[字幕脚本] 未找到字幕按钮,将重试"); setTimeout(tryOpenSubtitle, 1000); } }; tryOpenSubtitle(); } // 设置播放速度 async function setPlaybackRate(speed) { // 等待倍速菜单加载 const speedMenu = await waitForElm('.bpx-player-ctrl-playbackrate', 5000); if (!speedMenu) { console.warn("[字幕脚本] 未找到倍速控制元素"); return; } // 点击打开倍速菜单 speedMenu.click(); // 等待菜单项加载 await waitForElm('.bpx-player-ctrl-playbackrate-menu-item', 2000); // 尝试找到对应的倍速选项 let item = document.querySelector(`.bpx-player-ctrl-playbackrate-menu-item[data-value="${speed}"]`); // 如果直接找不到,尝试通过文本查找 if (!item) { const items = document.querySelectorAll('.bpx-player-ctrl-playbackrate-menu-item'); for (const i of items) { if (i.textContent.trim() === `${speed}x`) { item = i; break; } } } if (item) { item.click(); console.log("[字幕脚本] 设置倍速:", speed); } else { console.warn(`[字幕脚本] 未找到倍速 ${speed}x`); // 关闭菜单 speedMenu.click(); } } // 设置自动跳过片头片尾 function setupIntroOutroSkipper() { // 监听跳过按钮出现 const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { const skipButtons = document.querySelectorAll('.bpx-player-ctrl-jump-item, .jump-btn'); if (skipButtons.length > 0) { skipButtons[0].click(); console.log("[字幕脚本] 已自动跳过片头/片尾"); } } }); observer.observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false }); // 5分钟后停止观察,避免内存泄漏 setTimeout(() => observer.disconnect(), 300000); } // =============== 白名单管理 =============== function getWhitelist() { return GM_getValue('subtitleWhitelist', []); } function setWhitelist(arr) { GM_setValue('subtitleWhitelist', arr); } // =============== 倍速管理 =============== function getDefaultSpeed() { return GM_getValue('defaultPlaybackRate', null); } function setDefaultSpeed(value) { GM_setValue('defaultPlaybackRate', value); } function getOnlyWhitelistForSpeed() { return GM_getValue('onlyWhitelistForSpeed', false); } function setOnlyWhitelistForSpeed(value) { GM_setValue('onlyWhitelistForSpeed', value); } // =============== 跳过片头片尾管理 =============== function getSkipIntroOutro() { return GM_getValue('skipIntroOutro', false); } function setSkipIntroOutro(value) { GM_setValue('skipIntroOutro', value); } // 注册(不可用) Tampermonkey 菜单命令 GM_registerMenuCommand("设置字幕白名单", function() { const whitelist = getWhitelist(); const input = prompt("请输入UP主白名单(用英文逗号分隔)", whitelist.join(",")); if (input !== null) { const arr = input.split(",").map(x => x.trim()).filter(x => x); setWhitelist(arr); alert("已保存白名单: " + arr.join(", ") + ",刷新页面后生效"); } }); GM_registerMenuCommand("设置默认倍速", function() { const current = getDefaultSpeed() || "1"; const input = prompt("请输入默认倍速(可选: 2, 1.5, 1.25, 1, 0.75, 0.5)", current); if (input !== null) { const valid = ["2", "1.5", "1.25", "1", "0.75", "0.5"]; if (valid.includes(input)) { setDefaultSpeed(input); alert("已设置默认倍速: " + input + "x" + ",刷新页面后生效"); } else { alert("输入无效,请输入以下之一: " + valid.join(", ")); } } }); GM_registerMenuCommand("切换:倍速仅对白名单UP主生效", function() { const current = getOnlyWhitelistForSpeed(); setOnlyWhitelistForSpeed(!current); alert("倍速仅对白名单UP主生效: " + (!current ? "开启" : "关闭") + ",刷新页面后生效"); }); GM_registerMenuCommand("切换:自动跳过片头片尾", function() { const current = getSkipIntroOutro(); setSkipIntroOutro(!current); alert("自动跳过片头片尾: " + (!current ? "开启" : "关闭") + ",新视频生效"); }); // =============== 工具函数 =============== function waitForElm(selector, timeout = 10000) { return new Promise((resolve) => { // 立即检查 const element = document.querySelector(selector); if (element) { return resolve(element); } // 设置超时 const timer = setTimeout(() => { observer.disconnect(); resolve(null); // 超时返回null }, timeout); // 观察DOM变化 const observer = new MutationObserver(() => { const element = document.querySelector(selector); if (element) { clearTimeout(timer); observer.disconnect(); resolve(element); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } // 初始化 initUrlObserver(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址