// ==UserScript==
// @name 网页视频控制4.1【完美适配英导学院】
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.4.1
// @description 通过键盘快捷键控制网页视频播放:空格键播放/暂停,左右方向键快退/快进,上下方向键调节音量 | 完美适配英导学院嵌套iframe视频
// @author Trae & 优化版
// @match *://*/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// ✅ 核心优化:穿透iframe获取页面中所有视频元素,优先取正在播放/主视频
function getVideoElement() {
let video = document.querySelector('video');
// 先查主页面的视频
if (video && video.tagName === 'VIDEO') return video;
// 穿透所有iframe查询视频(解决英导学院核心问题)
const iframes = document.querySelectorAll('iframe');
for (let i = 0; i < iframes.length; i++) {
try {
video = iframes[i].contentDocument?.querySelector('video') || iframes[i].contentWindow?.document.querySelector('video');
if (video) break;
} catch (e) { /* 跨域iframe忽略,不影响使用 */ }
}
return video && video.tagName === 'VIDEO' ? video : null;
}
// 获取下一集视频的链接 - 优化匹配规则,适配英导学院课程链接
function getNextVideoLink() {
const videoLinks = Array.from(document.querySelectorAll('a')).filter(link => {
const href = link.href.toLowerCase();
const text = link.textContent.toLowerCase();
return href.includes('video') || href.includes('play') || href.includes('episode') ||
href.includes('course') || href.includes('lesson') ||
text.includes('集') || text.includes('期') || text.includes('课时') || text.includes('下一节');
});
if (videoLinks.length === 0) return null;
const currentIndex = videoLinks.findIndex(link => link.href === window.location.href);
if (currentIndex === -1 || currentIndex === videoLinks.length - 1) return null;
return videoLinks[currentIndex + 1].href;
}
// 跳转到下一集
function playNextVideo() {
const nextLink = getNextVideoLink();
if (nextLink) {
window.location.href = nextLink;
}
}
// 获取视频的唯一标识
function getVideoId(video) {
return `${window.location.href}-${video.currentSrc || video.src}`;
}
// 保存播放进度
function savePlaybackProgress(video) {
if (video && !video.paused && !isNaN(video.currentTime)) {
const videoId = getVideoId(video);
localStorage.setItem(videoId, video.currentTime.toString());
}
}
// 恢复播放进度
function restorePlaybackProgress(video) {
if (video && !isNaN(video.duration)) {
const videoId = getVideoId(video);
const savedTime = localStorage.getItem(videoId);
if (savedTime !== null) {
video.currentTime = Math.max(0, Math.min(video.duration, parseFloat(savedTime)));
}
}
}
// ✅ 核心优化:键盘事件处理 - 修复全屏失效、增加ESC退出全屏、防重复触发
function handleKeyPress(event) {
const video = getVideoElement();
if (!video) return;
// 只拦截控制视频的快捷键,不影响页面其他输入框/文本域
const controlKeys = ['Space','ArrowLeft','ArrowRight','ArrowUp','ArrowDown','KeyF','KeyN','Escape'];
if (controlKeys.includes(event.code) && !['INPUT','TEXTAREA'].includes(document.activeElement.tagName)) {
event.preventDefault();
event.stopPropagation();
}
switch(event.code) {
case 'Space': // 空格键:播放/暂停
video.paused ? video.play().catch(()=>{}) : video.pause();
break;
case 'ArrowLeft': // 左方向键:后退5秒
video.currentTime = Math.max(0, video.currentTime - 5);
break;
case 'ArrowRight': // 右方向键:前进5秒
video.currentTime = Math.min(video.duration || video.currentTime+5, video.currentTime + 5);
break;
case 'ArrowUp': // 上方向键:音量+10%
video.volume = Math.min(1.0, video.volume + 0.1).toFixed(1) * 1;
break;
case 'ArrowDown': // 下方向键:音量-10%
video.volume = Math.max(0.0, video.volume - 0.1).toFixed(1) * 1;
break;
case 'KeyN': // N键:跳转下一集
playNextVideo();
break;
case 'KeyF': // F键:全屏播放 - 修复多浏览器兼容+英导学院适配
if (video.requestFullscreen) video.requestFullscreen().catch(()=>{});
else if (video.webkitRequestFullscreen) video.webkitRequestFullscreen();
else if (video.mozRequestFullScreen) video.mozRequestFullScreen();
else if (video.msRequestFullscreen) video.msRequestFullscreen();
break;
case 'Escape': // ESC键:退出全屏 - 新增实用功能
if (document.exitFullscreen) document.exitFullscreen();
else if (document.webkitExitFullscreen) document.webkitExitFullscreen();
else if (document.mozCancelFullScreen) document.mozCancelFullScreen();
else if (document.msExitFullscreen) document.msExitFullscreen();
break;
}
}
// ✅ 核心优化:只绑定一次全局键盘事件,彻底解决全屏后重复绑定导致的失灵问题
document.removeEventListener('keydown', handleKeyPress); // 防重复挂载
document.addEventListener('keydown', handleKeyPress, true);
// 优化提示信息样式 - 不遮挡视频、更美观
const style = document.createElement('style');
style.textContent = `
.video-control-tips {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0,0,0,0.8);
color: #fff;
padding: 12px 15px;
border-radius: 8px;
font-size: 13px;
z-index: 999999;
display: none;
backdrop-filter: blur(5px);
border: 1px solid #333;
line-height: 1.6;
}
`;
document.head.appendChild(style);
const tips = document.createElement('div');
tips.className = 'video-control-tips';
tips.innerHTML = `
🎬 视频控制快捷键(适配英导学院)
␣ 空格 - 播放/暂停
← → 方向键 - 快退/快进5秒
↑ ↓ 方向键 - 音量±10%
F 键 - 全屏播放 | ESC - 退出全屏
N 键 - 跳转下一集/课时
`;
document.body.appendChild(tips);
// 监听视频元素出现 + 自动恢复进度 + 自动保存进度
const observer = new MutationObserver(() => {
const video = getVideoElement();
if (video && !video.dataset.binded) {
video.dataset.binded = 'true'; // 标记已绑定,防止重复执行
// 显示提示5秒
tips.style.display = 'block';
setTimeout(() => tips.style.display = 'none', 5000);
// 视频加载完成恢复进度
video.addEventListener('loadedmetadata', () => restorePlaybackProgress(video));
// 视频播放结束自动下一集
video.addEventListener('ended', () => {
savePlaybackProgress(video);
playNextVideo();
});
// 视频播放时实时保存进度(每3秒,性能更优)
setInterval(() => savePlaybackProgress(video), 3000);
// 页面离开强制保存进度
window.addEventListener('beforeunload', () => savePlaybackProgress(video));
}
});
// 监听页面所有节点变化,确保iframe加载后也能捕获到视频
observer.observe(document, { childList: true, subtree: true });
})();