[油猴脚本开发指南]h5视频倍速,时间加速和run-at
本节主要内容:视频加速与时间加速,会写一个用于:http://time.tianqi.com/的时间加速和用于bilibili的一个视频倍速:https://www.bilibili.com/video/BV1ys411p7To
时间加速例子已经失效,请去http://110.42.220.200/time.html实战
时间加速
首先来介绍一下时间加速的原理.一般情况下,都是使用setInterval来做定时器,我们只要把这个定时器的时间缩短,比如之前是1s触发一次,现在变成500ms触发一次,那么就相当于时间缩短了一倍.
怎么缩短呢?我们可以劫持setInterval这个函数,传入值为1000,我们把他变为500.代码类似下面这样:
```
let hookSetInterval=window.setInterval;//将系统提供的setInterval保存
window.setInterval=function(a,b){//将系统的setInterval替换为我们自己的
return hookSetInterval(a,b/2);//经过处理后再调用系统的setInterval
}
```
在脚本中也是类似的代码,不过如果使用//@grant unsafeWindow的话,window替换为unsafeWindow,
视频倍速
视频倍速的话,其实也很简单,主要牵扯到h5的video,里面有一个播放速度的属性:playbackRate,最高为16倍.
https://developer.mozilla.org/zh ... lement/playbackRate
像b站这个页面,里面只有一个视频,我们直接document.querySelector('video')就可以获取到了,如果有多个选择器写好也没问题.代码如下:
```
document.querySelector('video').playbackRate=2;
```
RUN-AT
注意这里还有一个比较重要的属性:// @run-at,:https://www.tampermonkey.net/documentation.php#_run_at
主要是设置脚本运行的时候.这里我们设置为:// @run-at document-start 希望脚本尽快的被注入,因为我们要抢在前端调用setInterval之前来替换掉setInterval函数.
脚本
知道上面的做法后,脚本也很容易写了,这次我们再来复习下之前的unsafeWindow和//@match.
代码我另外发帖了:https://bbs.tampermonkey.net.cn/thread-179-1-1.html
为什么我自己写了一个计时器hook不了设置grant none 和不设置都不行也设置了run-at
可以打印出提示 但是 计时器还是1秒的
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<span id="timer"></span>
</body>
<script>
var now = new Date();
var hour,minute,second;
hour = now.getHours();
minute = now.getHours();
second = now.getSeconds();
var func = () => {
document.querySelector('#timer').innerText = hour+':'+minute+':'+second;
second++;
};
setInterval(func, 1000);
</script>
</html>
脚本:
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @descriptiontry to take over the world!
// @author You
// @match http://127.0.0.1:5500/web/timer/index.html
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
(function() {
'use strict';
/* alert('hook');
let hookInterval = window.setInterval;
let cnt = 0;
let newInterval = (a,b)=>{
console.log('new interval',cnt);
cnt++;
return hookInterval(a,b*100);
};
window.setInterval = hookInterval;
console.log('ok'); */
console.log('begin');
let hookSetInterval=unsafeWindow.setInterval;//将系统提供的setInterval保存
unsafeWindow.setInterval=function(a,b){//将系统的setInterval替换为我们自己的
console.log('ok');
return hookSetInterval(a,7000);//经过处理后再调用系统的setInterval
}
})(); cao 发表于 2021-1-24 13:32
为什么我自己写了一个计时器hook不了设置grant none 和不设置都不行也设置了run-at
可以打印出提示 但 ...
这点应该是你是本地服务器,加载过快,脚本管理器还没有注入脚本
你试着卡一下网速看看
当输入run-at 只能保证管理器相对普通脚本尽快被注入,不能保证100%被注入
这点我视频提到过
不同的插件由于实现原理不同也存在不同的表现特性我记得
这是浏览器插件特性导致的,目前来看没什么特别好的解决方案
cao 发表于 2021-1-24 13:32
为什么我自己写了一个计时器hook不了设置grant none 和不设置都不行也设置了run-at
可以打印出提示 但 ...
你的代码太简单了,hook计时器的时候,已经被调用了
油猴的能力是尽可能的快,但是不能**完全保证**能够在页面的代码执行**前运行脚本**,这是浏览器扩展机制导致的
页面代码修改成这样就可以(增加了window.onload)
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<span id="timer"></span>
</body>
<script>
window.onload = function() {
var now = new Date();
var hour, minute, second;
hour = now.getHours();
minute = now.getHours();
second = now.getSeconds();
var func = () => {
document.querySelector('#timer').innerText = hour + ':' + minute + ':' + second;
second++;
};
setInterval(func, 1000);
}
</script>
</html>
```
谢谢哥哥们 哥哥们 我又遇到问题了 比如这个网站 https://player.alicdn.com/aliplayer/index.html
直接在网页控制台中设置 window.document.querySelector('video').playbackRate=8; 是可以加速的
但是 写在脚本里就不行
b站是正常的 。。aliplayer不知道为啥不行
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @descriptiontry to take over the world!
// @author You
// @match https://www.bilibili.com/video/*
// @match https://player.alicdn.com/aliplayer/index.html
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
let rate = 8;
'use strict';
unsafeWindow.onload=function(){
//在元素都加载完成后再监听video的播放时间,再进行倍速设置
unsafeWindow.document.querySelector('video').onplay=function(){
unsafeWindow.document.querySelector('video').playbackRate=rate;
}
}
cao 发表于 2021-1-26 14:23
哥哥们 我又遇到问题了 比如这个网站 https://player.alicdn.com/aliplayer/index.html
直接在网页控制台中 ...
!(data/attachment/forum/202101/26/143619qrzaz7fsekzh6qe6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
我调试了一下
1.每次暂停再播放,网站的代码会重置播放速度
2.第一次播放时应该是autoplay,onplay事件没有监听到,所以没有执行设置速率的那个代码
```
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @descriptiontry to take over the world!
// @author You
// @match https://www.bilibili.com/video/*
// @match https://player.alicdn.com/aliplayer/index.html
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
let rate = 8;
'use strict';
unsafeWindow.onload=function(){
unsafeWindow.document.querySelector('video').playbackRate=rate;
}
```
另外还可以加个计时器,定时设置速率,如果更复杂的话,就用hook,object.defineproperty(猜的,没实验)之类的技术,固定playbackRate属性,或者让他网页的js不重置倍速,暴力点可以直接计时器(计时器yyds)
cao 发表于 2021-1-26 14:23
哥哥们 我又遇到问题了 比如这个网站 https://player.alicdn.com/aliplayer/index.html
直接在网页控制台中 ...
这种情况一般因为程序自身跟脚本冲突了
脚本先执行一次速度,然后网页又复写了一次速度
解决这种办法一种是追终溯源,另外一种比较简单,直接加个延时跟网页错开
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @descriptiontry to take over the world!
// @author You
// @match https://www.bilibili.com/video/*
// @match https://player.alicdn.com/aliplayer/index.html
// @run-at document-start
// @grant unsafeWindow
// ==/UserScript==
let rate = 8;
'use strict';
unsafeWindow.onload=function(){
//在元素都加载完成后再监听video的播放时间,再进行倍速设置
unsafeWindow.document.querySelector('video').onplay=function(){
console.log('set')
unsafeWindow.setInterval(function(){ unsafeWindow.document.querySelector('video').playbackRate=rate; }, 3000);
}
} cao 发表于 2021-1-26 14:23
哥哥们 我又遇到问题了 比如这个网站 https://player.alicdn.com/aliplayer/index.html
直接在网页控制台中 ...
哥哥有小作品记得论坛发布一下~ ok~ 谢谢大佬们