// ==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 }); })();