// ==UserScript== // @name 倍速播放 // @namespace https://gitee.com/yellownacl // @version 1.0 // @description HTML5播放器,倍速|最高10倍|计时器掌控者|视频跳过广告|视频广告加速 // @author 黄盐 // @include *:* // @grant none // @run-at document-end // @require https://greasyfork.org/scripts/420615-cangshi-everything-hook/code/Cangshi-Everything-Hook.js?version=893832 // @require https://greasyfork.org/scripts/420618-cangshi-timerhooker/code/Cangshi-TimerHooker.js?version=893838 // @downloadURL https://update.greasyfork.icu/scripts/383265/%E5%80%8D%E9%80%9F%E6%92%AD%E6%94%BE.user.js // @updateURL https://update.greasyfork.icu/scripts/383265/%E5%80%8D%E9%80%9F%E6%92%AD%E6%94%BE.meta.js // ==/UserScript== /* jshint esversion: 6 */ const defaltLocalStorage = {speed: 1, position: {left: 50, top:100}, speedArray: [1, 2, 3, 15]}; // localStorage 默认值 // 因为外部资源脚本不允许 @grant GM_getValue 和 GM_setValue,暂时只能用本地存储替代扩展存储数据。 function GM_getValue(key, defaultValue){ let res = localStorage.getItem('tampermonkeySpeedy') if(res){ res = JSON.parse(res) }else{ res = Object.assign({}, JSON.parse(JSON.stringify(defaltLocalStorage))) } if(res[key]){ return res[key] }else{ return defaultValue } } function GM_setValue(key,value){ let res = localStorage.getItem('tampermonkeySpeedy') if(res){ res = JSON.parse(res) }else{ res = Object.assign({}, JSON.parse(JSON.stringify(defaltLocalStorage))) } res[key] = value localStorage.setItem('tampermonkeySpeedy', JSON.stringify(res)) } function isNumber(obj){ // 这个方法网络上找来的,对于整数,浮点数返回true,对于NaN或可转成NaN的值返回false。 return obj === +obj } function querySelectorAll(parentNode, selector){ let elements = parentNode.querySelectorAll(selector) elements = Array.prototype.slice.call(elements || []) return elements } function changeSpeed(rate, isInit=false){ if(!isNumber(rate)){ rate = parseFloat(rate) if(!isNumber(rate)) { log('不能转为速度') return false } } timer.change(1/rate) if(!isInit){GM_setValue('speed', rate)} return rate } function log(message,msgType="normal"){ let style = { hint: `background:#ff0; border-left: 5px solid #333; padding:1px 3px; font-weight:bold;`, normal: `background:lightgreen;padding:1px 5px 1px 2px; border-right: 3px solid darkblue;`, warning: `background:#FFFBE5;padding:1px 5px 1px 2px; border-right: 3px solid darkblue;`, error: `background:red;padding:1px 5px 1px 2px; border-right: 3px solid darkblue;` }; console.log("%c SpeedyPlay Info: %c"+message, style.hint, style[msgType]); } function getSideSpeed(){ return GM_getValue('speed', 1.0) } function getSitePosition(){ return GM_getValue('position', {left: 50, top: 100}) ; } function saveSpeed(speed){ if(!isNumber(speed)){ log(`速度值设置错误,应该提供数值类型,${speed} 是 ${typeof speed} 类型!`, 'error'); return false; } GM_setValue('speed', speed); return true; } function savePosition(left, top){ try { if(typeof left != 'number' || typeof top != 'number'){ log(`位置值设置错误,应该提供数值类型,现在 left:${typeof left},top: ${typeof top}`, 'error'); return false; } GM_setValue('position', {left: left,top: top}); log(left+'--'+top); return true; } catch (error) {} log("savePosition", left, top) } function saveSpeedArray(speedArray){ GM_setValue('speedArray', speedArray); } function initSpeedy(){ const speedData = { currentSpeed: GM_getValue('speed'), speedArray: GM_getValue('speedArray'), // 常用速度列表,比如2x,3x, 常规观看 10x,15x用来跳过广告。最多6个 editArray: false, // 速度状态是否处于可编辑装填,如果是,点击就没有反应,如果不是,点击就改变速度 lastTimeSpeed: 1, // 上次的速度,方便在2种速度之间切换,区分站点存储, position: GM_getValue('position'), // 控件的位置,区分站点存储 } const speedyHandler = { set(target, prop, value){ switch(prop){ case "currentSpeed" : target["lastTimeSpeed"] = target["currentSpeed"] target[prop] = value currentSpeedElem.value = value speedText.innerHTML = value currentSpeedElem.setAttribute("style", `background-size:${value*10}% 100%`) changeSpeed(value) break; case "editArray": target[prop] = value if(speedState.editArray){ speedArrayElems.forEach(element=>{ element.setAttribute("contenteditable", "true") }) editArrayButton.innerHTML = "保存" } else { let tmp = [] speedArrayElems.forEach(element=>{ element.removeAttribute("contenteditable") tmp.push(parseFloat(element.dataset.value)) }) editArrayButton.innerHTML = "编辑" speedState.speedArray = tmp saveSpeedArray(speedState.speedArray) } break; default: target[prop] = value // log(prop +' → '+ value.toString()) break; } } } // 创建元素 const node = document.createElement("DIV") let nodeHTML = `