我关于某些视频网站缓存不会自动加载的问题的解决方案

2025-10-25 03:32:54

当观看网站的在线视频的时候, 底下进度条后面还有一个半透明的缓冲条,当进度条达到透明条的地方,视频就会卡一下,然后半透明进度条会往前一下 ,也就是说看视频的时候每过一分钟就会个几秒.

根据我的观察,b站的几分钟的短视频,20分钟左右的番剧的缓冲条都是会自动加载的,正常播放不会有卡顿,而我在看一些时间较长的音乐视频的时候,我希望在后台自动播放,但是他会每分钟卡个几秒,这就很影响体验。这应该也是b站的单宽策略所致。

那如何解决呢?经过手动测试,当在进度条上点击任意时间的时候,缓冲时间就会填满到1分钟左右的时间,于是我让ai写了脚本

// ==UserScript==

// @name B站精准阈值缓冲器

// @namespace http://tampermonkey.net/

// @version 5.1

// @description 当剩余缓冲不足指定秒数时触发无感加载

// @match *://*.bilibili.com/*

// @grant unsafeWindow // 需要特殊权限访问页面音频系统

// @run-at document-idle // 等页面完全加载后执行

// ==/UserScript==

(function() {

'use strict';

// ================= 配置参数 =================

const BUFFER_THRESHOLD = 5; // 当剩余缓冲时间少于5秒时触发预加载

const CHECK_INTERVAL = 2000; // 每2秒检查一次缓冲状态(毫秒)

const MICRO_SEEK = 0.00001; // 10微秒的极小跳转量(人耳不可感知)

// ================= 状态控制 =================

let isOperating = false; // 防止重复触发锁

const audioContext = new (window.AudioContext || window.webkitAudioContext)(); // 创建独立音频上下文

let mediaElementSource = null; // 音频管道连接器

/**

* 计算当前播放位置之后的剩余缓冲时间

* @param {HTMLVideoElement} video - 视频元素

* @return {number} 剩余缓冲秒数

*

* 原理:遍历video.buffered对象,找到包含当前播放时间的缓冲区间,

* 然后用区间结束时间减去当前时间得到剩余缓冲

*/

function getRemainingBuffer(video) {

for (let i = 0; i < video.buffered.length; i++) {

if (video.buffered.start(i) <= video.currentTime &&

video.buffered.end(i) >= video.currentTime) {

return video.buffered.end(i) - video.currentTime;

}

}

return 0; // 没有找到有效缓冲区间

}

/**

* 核心缓冲触发函数(完全无感知实现)

*

* 实现原理:

* 1. 极微小地调整播放位置(10微秒)

* 2. 通过Web Audio API保持音频连续性

* 3. 1毫秒内立即恢复原位置

*

* 这样触发了浏览器的缓冲机制,但用户完全感知不到

*/

function triggerStealthBuffer() {

if (isOperating) return; // 防止重复执行

// 兼容新旧版B站播放器(含Shadow DOM情况)

const video = document.querySelector('.bpx-player-container')?.shadowRoot?.querySelector('video')

|| document.querySelector('video');

if (!video || video.paused || video.readyState < 3) return; // 视频未就绪时跳过

const remainingBuffer = getRemainingBuffer(video);

if (remainingBuffer > BUFFER_THRESHOLD) return; // 缓冲充足时不操作

isOperating = true; // 加锁

// 初始化音频管道(防止操作导致音频卡顿)

if (!mediaElementSource) {

mediaElementSource = audioContext.createMediaElementSource(video);

mediaElementSource.connect(audioContext.destination);

}

const originalTime = video.currentTime;

// 量子级操作(核心技巧)

video.currentTime = originalTime + MICRO_SEEK; // 极小幅度跳转

setTimeout(() => {

video.currentTime = originalTime; // 极速恢复原位

isOperating = false; // 解锁

console.debug(`[幽灵缓冲] 已触发 | 剩余缓冲: ${remainingBuffer.toFixed(2)}秒`);

}, 1); // 1毫秒延迟确保稳定性

}

/**

* 智能初始化系统

*

* 等待播放器加载完成后再启动检测循环

* 采用轮询方式确保兼容动态加载的播放器

*/

function init() {

const video = document.querySelector('video, .bpx-player-container');

if (video) {

setInterval(triggerStealthBuffer, CHECK_INTERVAL); // 启动定时检测

console.log('✅ 精准缓冲系统已激活 | 配置:', {

触发阈值: `${BUFFER_THRESHOLD}秒`,

检测频率: `${CHECK_INTERVAL}ms`,

跳转幅度: `${MICRO_SEEK}秒`

});

} else {

setTimeout(init, 1000); // 未找到播放器则1秒后重试

}

}

// ================= 启动逻辑 =================

if (document.readyState === 'complete') {

init(); // 页面已加载完成直接启动

} else {

window.addEventListener('load', init); // 否则等待页面加载

}

})();

使用油猴运行

会在缓冲区即将到头的时候小小的卡一下下,但是相比原先好太多了