您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
记住B站视频或专辑播放进度
// ==UserScript== // @author yungyu16 // @name BiliBili记住播放进度 // @description 记住B站视频或专辑播放进度 // @namespace yungyu16/bilibili-helper // @version 1.0 // @website https://github.com/yungyu16/bilibili-helper // @supportURL https://github.com/yungyu16/bilibili-helper/issues // @supportURL https://raw.githubusercontent.com/yungyu16/bilibili-helper/master/index.js // @include http*://www.bilibili.com/video/av* // @include http*://www.bilibili.com/video/BV* // @require https://lib.baomitu.com/qs/6.9.3/qs.min.js // @require https://lib.baomitu.com/jquery/3.5.1/jquery.slim.min.js // @grant GM_log // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @grant unsafeWindow // ==/UserScript== const FLAG_DEBUG = false; const REDIRECT_FLAG = '__bh_r_f'; //__bhelper_redirect_flag__ (function () { 'use strict'; let videoEl = $(".bilibili-player-video video").get(0); let videoId = extractCurVideoId(); let settingKey = settingKeyBuilder(videoId); doWithDebugMode(() => GM_log("当前视频id:", videoId)); //恢复播放上下文 switchPlayContext(); //保存播放上下文 savePlayContext(); //=========================================== // 正文开始 //=========================================== /** * 切换播放上下文 */ function switchPlayContext() { let lastPage = GM_getValue(settingKey("lastPage"), 1); let pageNo = extractCurPageNo(); let pageList = $('.list-box li'); let pageCount = pageList.length; doWithDebugMode(() => { GM_log("lastPage:", lastPage); GM_log("pageCount:", pageCount); }); //重定向到指定集 if (pageNo > 0) { doWithDebugMode(() => GM_log("指定集数播放...无需重定向")); } if (pageCount > 0 && pageNo < 0 && lastPage > 1) { //当前链接没有携带集数参数 if ((pageNo) !== (lastPage / 1)) { let thisQueryParams = parseQueryString(); thisQueryParams.p = lastPage; setRedirectFlag(thisQueryParams); //添加重定向标记 location.href = `/video/${videoId}?${Qs.stringify(thisQueryParams)}` } } //设置播放进度 if (getRedirectFlag()) { //检查重定向标记 let lastTime = GM_getValue(settingKey("lastTime"), 0); doWithDebugMode(() => GM_log("lastTime:", lastTime)); if (lastTime > 0) { setTimeout(() => { if (videoEl.currentTime > 10) { GM_log("B站已自动同步播放进度,无需重新定位"); return; } videoEl.currentTime = lastTime; let progressMsg = `已定位到历史播放进度:${formatProgressSecond(lastTime)}`; doWithDebugMode(() => { let notifyParam = { title: "bilibili-helper", text: progressMsg, silent: true, timeout: 3000, }; GM_notification(notifyParam); }); GM_log("progressMsg:", progressMsg); videoEl.play(); }, 4 * 1000); } } } /** * 定时持久化播放上下文到 */ function savePlayContext() { setInterval(doSavePlayContext, 5 * 1000); } /** * 持久化播放上下文到 */ function doSavePlayContext() { let pageNo = extractCurPageNo(); let currentTime = videoEl.currentTime; GM_setValue(settingKey("lastPage"), pageNo); GM_setValue(settingKey("lastTime"), currentTime <= 0 ? 0 : currentTime); doWithDebugMode(() => GM_log("lastPage:", pageNo, ",lastTime:", formatProgressSecond(currentTime))); } /** * 调试命令 */ function doWithDebugMode(action) { try { if (FLAG_DEBUG) { action(); } } catch (e) { GM_log("Bhelper调试指令执行异常:", e); } } /** * 播放进度格式化 */ function formatProgressSecond(lastTime) { return `${Math.floor(lastTime / 60)}m${Math.floor(lastTime % 60)}s`; } /** * 拼接videoId av号、BV号 */ function settingKeyBuilder(bv) { return function (key) { return bv + ":" + key; } } /** * 抽取videoId av号、BV号 */ function extractCurVideoId() { let pathname = location.pathname; if (!pathname) { return undefined; } if (pathname.endsWith("/")) { pathname = pathname.substring(0, pathname.length - 1); } return pathname.substr(pathname.lastIndexOf('/') + 1); } /** * 抽取pageNo 当前集数 */ function extractCurPageNo() { let queryParams = parseQueryString(); return queryParams.p ? queryParams.p : -1; } /** * 解析url参数 */ function parseQueryString() { let searchStr = location.search; if (!searchStr) { return {}; } return Qs.parse(searchStr.substr(1)); } /** * 获取重定向标记,获取一次后删除 */ function getRedirectFlag() { let queryParams = parseQueryString(); let redirectFlag = queryParams[REDIRECT_FLAG]; delete queryParams[REDIRECT_FLAG]; history.pushState(null, null, `${location.pathname}?${Qs.stringify(queryParams)}`); return redirectFlag; } /** * 设置重定向标记 */ function setRedirectFlag(obj) { obj[REDIRECT_FLAG] = 1; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址