Tampermonkey 脚本开发记录:自动化播放学习视频
Kecho

本文主要想记录一下我的第一个 Tampermonkey 脚本。

有这样一个内部视频学习平台,每月都要求学习指定视频,视频的内容和质量懂得都懂,于是就想利用 Tampermonkey 脚本来实现自动学习,功能如下:

  • 移除窗口最小化或鼠标离开窗口时自动暂停视频的限制
  • 更改默认播放速度
  • 自动切换下一章节播放

代码由 AI 辅助生成,@match 中域名已匿名化,仅试用于特定平台。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// ==UserScript==
// @name 自动播放视频
// @namespace https://www.kecho.top
// @version 1.1.0
// @description 防止切屏或点击其它地方导致视频暂停;自动切换下一章节视频
// @author Kecho
// @match https://xxx.example.com/dlp-webapp/course/learning/*
// @match http://xxx.example.com/dlp-webapp/course/learning/*
// @grant none
// ==/UserScript==

(function() {
'use strict';
function waitForIframe(selector, callback, timeout = 5000) {
const start = Date.now();

(function poll() {
const iframe = document.querySelector(selector);
if (iframe) {
callback(iframe);
} else if (Date.now() - start < timeout) {
requestAnimationFrame(poll);
} else {
console.warn("⚠️ iframe 等待超时");
}
})();
}
function monitorVideoPlay(container) {
const observer = new MutationObserver(() => {
const video = container.body.querySelector('video');
if (video && video.paused) {
console.log('✅ 播放 video');
video.addEventListener('timeupdate', e => {
e.stopImmediatePropagation();
e.stopPropagation();
}, true);
video.playbackRate = 10;
video.defaultPlaybackRate = 10;
video.muted = true;
video.play().catch(console.warn);
}
});

observer.observe(container.body, {
childList: true,
subtree: true
});
}

// 等待 iframe 加载
function main() {
waitForIframe('iframe', (iframe) => {
// 防止窗口最小化被暂停
Object.defineProperty(Document.prototype, 'hidden', {get: () => false});
// 防止鼠标点击其它处被暂停
['blur', 'visibilitychange', 'webkitvisibilitychange'].forEach(evt => {
iframe.contentWindow.addEventListener(evt, e => {
e.stopImmediatePropagation();
e.stopPropagation();
}, true);
});
iframe.addEventListener('load', () => {
const checkVideo = () => {
try {
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
console.log('✅ video 准备好');
// 监听 video 加载完成
monitorVideoPlay(iframeDoc);
// 视频未播放完成时可能已经可以下一章
const interval = setInterval(() => {
const nextBtn = iframeDoc.querySelectorAll('.submit-quiz-button button')[0];
if (nextBtn) {
const isDisabled = nextBtn.disabled || nextBtn.getAttribute('aria-disabled') === 'true' || nextBtn.classList.contains('disabled');

if (!isDisabled) {
if(nextBtn.innerText === '下一页'){
console.log('✅ 跳转下一章节');
nextBtn.click();
}else if(nextBtn.innerText === '完成学习'){
console.log('✅ 完成学习');
nextBtn.click();
clearInterval(interval);
}else {
clearInterval(interval);
}
}
}
}, 500);

} catch (e) {
console.error('❌ 跨域访问错误:', e);
}
};
checkVideo();
});
});
}
main();
})();
 评论
评论插件加载失败
正在加载评论插件
总字数 29.4k