点击开始播放
// ==UserScript== // @name 百度网盘在线视频播放器 // @namespace https://example.com/ // @version 3.12 // @description 百度网盘视频在线播放,支持倍速调节(0.25x-4x)、画质切换(360P-1080P),记忆播放进度,新标签页打开 // @match https://pan.baidu.com/s/* // @grant unsafeWindow // @run-at document-start // @icon https://nd-static.bdstatic.com/m-static/wp-brand/favicon.ico // @license MIT // ==/UserScript== (function() { 'use strict'; var PROGRESS_EXPIRY_DAYS = 7; var EXPIRY_MS = PROGRESS_EXPIRY_DAYS * 24 * 3600 * 1000; function isTouchDevice() { return ('ontouchstart' in window) || (navigator.maxTouchPoints > 0); } function isTablet() { return isTouchDevice() && window.innerWidth >= 600; } function getPageWindow() { try { if (typeof unsafeWindow !== 'undefined' && unsafeWindow) return unsafeWindow; } catch (e) {} try { if (window.wrappedJSObject) return window.wrappedJSObject; } catch (e) {} return window; } function getFileName(file) { return file.server_filename || file.filename || file.name || file.title || '未知文件'; } function getFolderName() { var hash = location.hash; var match = hash.match(/path=([^&]+)/); if (match) { var path = decodeURIComponent(match[1]); var idx = path.indexOf('sharelink'); if (idx >= 0) { var sub = path.substring(idx); var parts = sub.split('/'); if (parts.length > 1) parts.shift(); return parts.join('/') || '根目录'; } return path || '根目录'; } return '根目录'; } function getSurId() { return (location.pathname.match(/\/s\/(\w+)/) || [])[1] || ''; } // ============ 多途径获取 jsToken(关键修复) ============ function getJsToken() { var pageWin = getPageWindow(); // 1. 新版百度网盘直接挂在 window.jsToken 上(参考脚本验证) try { if (pageWin.jsToken) return pageWin.jsToken; } catch (e) {} try { if (window.jsToken) return window.jsToken; } catch (e) {} // 2. locals 里的字段 try { var locals = pageWin.locals || {}; if (locals.jsToken) return locals.jsToken; if (locals.token) return locals.token; } catch (e) {} // 3. 已捕获的网络请求缓存 try { if (window.__bdTokenCache) return window.__bdTokenCache; if (pageWin.__bdTokenCache) return pageWin.__bdTokenCache; } catch (e) {} // 4. 从页面 script 标签提取 try { var scripts = document.querySelectorAll('script'); for (var i = 0; i < scripts.length; i++) { var text = scripts[i].textContent; if (!text || text.indexOf('jsToken') === -1) continue; var m = text.match(/jsToken["']?\s*[:=]\s*["']([^"']+)["']/); if (m && m[1]) return m[1]; } } catch (e) {} return ''; } // ============ 页面级网络劫持(捕获 jsToken / adToken) ============ (function hookNetwork() { if (window.__bdTokenHooked) return; window.__bdTokenHooked = true; window.__bdTokenCache = window.__bdTokenCache || ''; window.__bdAdTokenCache = window.__bdAdTokenCache || ''; function captureFromUrl(url) { if (!url || typeof url !== 'string') return; var m = url.match(/[?&]jsToken=([^&]+)/); if (m && m[1]) window.__bdTokenCache = decodeURIComponent(m[1]); } try { var originalFetch = window.fetch; window.fetch = function() { try { var url = arguments[0]; if (typeof url === 'string') captureFromUrl(url); else if (url && url.url) captureFromUrl(url.url); } catch (e) {} return originalFetch.apply(this, arguments); }; } catch (e) {} try { var originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { try { captureFromUrl(url); } catch (e) {} return originalOpen.apply(this, arguments); }; } catch (e) {} })(); function getCurrentList() { try { var pageWin = getPageWindow(); var locals = pageWin.locals; if (locals && locals.file_list && locals.file_list.length) { sessionStorage.setItem(getSurId(), JSON.stringify(locals.file_list)); return locals.file_list; } } catch (e) {} try { var ctx = unsafeWindow.require('system-core:context/context.js'); var list = ctx.instanceForSystem.list.getCurrentList(); if (list && list.length) { sessionStorage.setItem(getSurId(), JSON.stringify(list)); return list; } } catch (e) {} try { if (unsafeWindow.__LIST__ && unsafeWindow.__LIST__.length) { sessionStorage.setItem(getSurId(), JSON.stringify(unsafeWindow.__LIST__)); return unsafeWindow.__LIST__; } } catch (e) {} var scripts = document.querySelectorAll('script'); for (var i = 0; i < scripts.length; i++) { var text = scripts[i].textContent; if (text && text.indexOf('"list":[') !== -1 && text.indexOf('"category"') !== -1) { try { var match = text.match(/"list":(\[.*?\]),/) || text.match(/"list":(\[.*?\])/); if (match) { var list = JSON.parse(match[1]); if (list && list.length) { sessionStorage.setItem(getSurId(), JSON.stringify(list)); return list; } } } catch (e) {} } } var cached = sessionStorage.getItem(getSurId()); if (cached) { try { return JSON.parse(cached); } catch (e) {} } return []; } function filterVideos(list) { if (!list || !list.length) return []; return list.filter(function(i) { if (i.hasOwnProperty('category')) return i.category === 1; var name = getFileName(i).toLowerCase(); return /\.(mp4|mkv|webm|avi|mov|flv|wmv|ts|m3u8)$/i.test(name); }); } function getCachedVideoList(surId) { var key = 'bd_video_cache_' + surId; var cached = localStorage.getItem(key); if (cached) { try { return JSON.parse(cached); } catch (e) {} } return null; } function safeJsonStringify(obj) { return JSON.stringify(obj).replace(/<\/script>/gi, '<\\/script>'); } function cleanExpiredProgress() { var now = Date.now(); var keysToRemove = []; for (var i = 0; i < localStorage.length; i++) { var key = localStorage.key(i); if (key && (key.indexOf('bd_play_progress_') === 0 || key.indexOf('bd_last_path_') === 0)) { try { var data = JSON.parse(localStorage.getItem(key)); if (data && data.time) { var age = now - data.time; if (age > EXPIRY_MS) { keysToRemove.push(key); } } } catch (e) {} } } keysToRemove.forEach(function(key) { localStorage.removeItem(key); }); } // ============ 构建完整播放器页面 ============ function buildPlayerPage(videoList, shareInfo, folderName) { if (!videoList || !videoList.length) { var surId0 = getSurId(); var cachedList = getCachedVideoList(surId0); if (cachedList && cachedList.length) { videoList = cachedList; } else { return '
当前文件夹没有视频文件
'; } } var surId = getSurId(); var isTabletDevice = isTablet(); var enhancedVideos = []; videoList.forEach(function(v, idx) { var name = getFileName(v); var fid = v.fs_id || v.fid || v.id || ('fid_' + idx); if (name && fid) { enhancedVideos.push({ id: idx, name: name, fid: fid, duration: 0, fullPath: surId + '|' + folderName + '/' + name }); } }); enhancedVideos.sort(function(a, b) { return a.name.localeCompare(b.name, 'zh-CN', { numeric: true }); }); enhancedVideos.forEach(function(v, i) { v.id = i; }); var videoDataLiteral = safeJsonStringify(enhancedVideos); var shareDataLiteral = safeJsonStringify(shareInfo); var folderLiteral = safeJsonStringify(folderName); var dirKey = surId + '|' + folderName; var hlsCdn1 = 'https://cdnjs.cloudflare.com/ajax/libs/hls.js/1.6.6/hls.min.js'; var hlsCdn2 = 'https://unpkg.com/hls.js@1.6.6/dist/hls.min.js'; var hlsCdn3 = 'https://cdn.jsdelivr.net/npm/hls.js@1.6.6/dist/hls.min.js'; var jsCode = []; jsCode.push('(function(){'); jsCode.push('var hlsCdns = ' + safeJsonStringify([hlsCdn1, hlsCdn2, hlsCdn3]) + ';'); jsCode.push('var vd = ' + videoDataLiteral + ';'); jsCode.push('var sd = ' + shareDataLiteral + ';'); jsCode.push('var folder = ' + folderLiteral + ';'); jsCode.push('var dirKey = ' + safeJsonStringify(dirKey) + ';'); jsCode.push('var EXPIRY_MS = ' + EXPIRY_MS + ';'); jsCode.push('console.log("[播放器] sd =", JSON.stringify(sd));'); jsCode.push('function $(id){return document.getElementById(id)}'); jsCode.push('var ve=$("video"),ov=$("ovl"),ib=$("info-text"),pb=$("pbar"),pf=$("pfill"),tl=$("tlabel"),vl=$("vlist"),sx=$("search"),spd=$("speed-select"),qsel=$("quality-select"),vsl=$("vol-slider"),pa=$("p-area"),ovt=$("ovl-text"),cpb=$("copy-btn"),toast=$("toast");'); jsCode.push('var sb=$("sidebar"),rs=$("resizer"),foldBtn=$("fold-sidebar-btn"),unfoldBtn=$("unfold-sidebar"),toggleSidebarBtn=$("toggle-sidebar-btn"),pipBtn=$("pip-btn"),fullscreenBtn=$("fullscreen-btn"),mainEl=$("main");'); jsCode.push('var volIcon=$("vol-icon");'); jsCode.push('var ci=-1,cq=1080,hs=null,drg=false,curUrl="",curSpeed=1,sideVisible=true,saveTimer=null,endedFlag=false,_lastTimeUpdate=-1,curAdToken="";'); jsCode.push('var fullscreenHideTimer=null,isFullscreen=false,controlsVisible=true;'); jsCode.push('function fmtDur(s){if(!s||s<=0)return"";s=Math.floor(s);var h=Math.floor(s/3600),m=Math.floor((s%3600)/60),sec=s%60;return h>0?h+":"+String(m).padStart(2,"0")+":"+String(sec).padStart(2,"0"):m+":"+String(sec).padStart(2,"0")}'); jsCode.push('function ft(t){if(isNaN(t)||t===Infinity||t<0)return"0:00";var h=Math.floor(t/3600),m=Math.floor((t%3600)/60),s=Math.floor(t%60);return h>0?h+":"+String(m).padStart(2,"0")+":"+String(s).padStart(2,"0"):m+":"+String(s).padStart(2,"0")}'); jsCode.push('function saveProgress(){if(ve.ended||endedFlag)return;if(ci>=0&&vd[ci]&&vd[ci].fid&&ve.currentTime>0){var data={time:Date.now(),progress:ve.currentTime};localStorage.setItem("bd_play_progress_"+vd[ci].fid,JSON.stringify(data))}}'); jsCode.push('function getProgress(fid){var key="bd_play_progress_"+fid,st=localStorage.getItem(key);if(!st)return 0;try{var d=JSON.parse(st);if(d&&d.time&&d.progress){if(Date.now()-d.time>EXPIRY_MS){localStorage.removeItem(key);return 0}return d.progress}}catch(e){}return 0}'); jsCode.push('function saveLastVideoPath(v){if(!v||!v.fullPath)return;localStorage.setItem("bd_last_path_"+dirKey,JSON.stringify({time:Date.now(),fullPath:v.fullPath}))}'); jsCode.push('function getLastVideoIndex(){var st=localStorage.getItem("bd_last_path_"+dirKey);if(!st)return-1;try{var d=JSON.parse(st);if(d&&d.time&&d.fullPath&&Date.now()-d.time<=EXPIRY_MS){for(var i=0;i点击开始播放