// ==UserScript== // @name myBilibiliVideoTools-解耦版 // @简称 mbvt // @namespace http://tampermonkey.net/ // @match https://www.bilibili.com/video/* // @match https://www.bilibili.com/bangumi/play/* // @match https://www.le.com/ptv/vplay/* // @icon http://bilibili.com/favicon.ico // @noframes // @run-at document-idle // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @compatible firefox // @description 我本人在哔哩哔哩看视频的专用工具,尽测试过火狐,内置多个功能,可以设置倍速,音量,全屏等.本脚本永久开源,永久免费。本脚本不得被用于任何的非法用途,仅能被合法的学习和使用。如果您安装了本脚本,产生的一切后果均由您承担,本人概不负责。本脚本的后续更新与否只取决于本人的心情。 // @license MIT // @version 0.0.1.20230103174800 // @downloadURL none // ==/UserScript== let myRateSelector,myVolumeSelector,myFullscreenBtn,vedio,playFlag; const sv=GM_setValue,gv=GM_getValue,as=GM_addStyle; /* 缺点:全屏后较为单调.且火狐必须先配置浏览器.功能少. 优点:强解耦 */ /*添加元素,仅执行一次*/ (function addEles(){ const s=document.createElement('script'); s.src="https://greasyfork.org/scripts/435697-myutils/code/myUtils.js?version=1074160"; document.head.append(s); s.onload=()=>{ as(`#mbvt_root{ position: fixed; top: 30% !important; right: 0 !important; z-index: 9999999; }/*video{ width: 100%;height: 100%;position: fixed;z-index: 1659548286991;left: 0;top: 0;background: black; }*/`); const root=my.append(`div`,my.zone,'',`id`,'mbvt_root'),//总div rateData = { select倍速:1, '0.5x':0.5,'1.0x':1,'1.5x':1.5,'2.0x':2.0 }, rateDataLen = rateData.length, rateSelector = my.append(`select`,null), volumeData = { select音量:1,'0%':0,'10%':0.1,'100%':1 }, volumeSelector = my.append(`select`,null), fullscreenBtn=my.append(`button`,null,'fullscreen').on('click',()=>{ vedio.requestFullscreen(); }), playBtn=my.append(`button`,null,'play','style','color: white;background: black').on('mouseover',()=>{ vedio.play(); }); for (const key in rateData) my.append(`option`,rateSelector,key,`value`,rateData[key]); for (const key in volumeData) my.append(`option`,volumeSelector,key,`value`,volumeData[key]); rateSelector.onchange=e=>{ const t=e.target, i=t.selectedIndex, rate=t.options[i].value; if(i.selectedIndex===0) return; vedio.playbackRate=rate; sv('rateIndex',i); t.children[0].selected = true; } volumeSelector.onchange=e=>{ const t=e.target, i=t.selectedIndex, volume=t.options[i].value; if(i.selectedIndex===0) return; vedio.volume=volume; sv('volumeIndex',i); t.children[0].selected = true; } divAppendDivWithEle(root,rateSelector,volumeSelector,playBtn,fullscreenBtn); myRateSelector=rateSelector; myVolumeSelector=volumeSelector; myFullscreenBtn=fullscreenBtn; return init() } })() /*初始化倍速,音量,全屏*/ function init(){ // console.log('触发init') const v=document.querySelector('video');//作为网页加载好的flag if(!v){ console.log("video not found, retry after 1000ms..."); return setTimeout(init,1000); }else{//已加载好.对第一次视频的初始化 // console.log(v) observeVideo(vedio=v); playFlag=1; v.onplay=()=>{ // alert(1) myFullscreenBtn.click() return (playFlag<2)&&(playFlag++)&&(()=>{ v.volume=myVolumeSelector.children[gv('volumeIndex',0)].value; v.playbackRate=myRateSelector.children[gv('rateIndex',0)].value; })() } myFullscreenBtn.click() v.focus(); } } /*div套子div,子div套实质ele*/ function divAppendDivWithEle(dad,...elements){ elements.forEach(e=>{ my.append(e,my.append(`div`,dad)); }) } /*观察video*/ function observeVideo(video){ const targetNode = video, config = { attributes: true, attributeFilter: ["src"], childList: false, subtree: false }, // 当观察到变动时执行的回调函数 callback = function(mutations, observer) { for(let mutation of mutations) { if (mutation.type == 'attributes') { // 触发换源:清晰度改变/下一个视频/网络波动 //换源前半:video标签丢失,mutation.target.src由实变为'' //换源后半:video标签不丢失,mutation.target.src由''变为实 if(mutation.target.src){ // console.log('触发换源后半') observer.disconnect(); //重新初始化 init(); } } } }, // 创建一个观察器实例并传入回调函数 observer = new MutationObserver(callback); observer.observe(targetNode, config); }