// ==UserScript==
// @name Plyr Video Controller Pro
// @namespace http://tampermonkey.net/
// @version 1.4
// @description 带浮动控制面板的Plyr视频控制器(播放时触发跳转)
// @author glenn
// @match http://dxzx.ouc.edu.cn/*
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @run-at document-end
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// 配置存储
const config = {
autoSkip: GM_getValue('autoSkip', true),
enableSeek: GM_getValue('enableSeek', true),
playbackSpeed: GM_getValue('speed', 2.0),
skipDelay: GM_getValue('delay', 100),
debugMode: GM_getValue('debug', true)
};
// 添加浮动面板样式(保持原图简洁风格)
GM_addStyle(`
#plyr-control-panel {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background: white;
color: black;
padding: 10px;
border-radius: 5px;
font-family: monospace;
box-shadow: 0 0 5px rgba(0,0,0,0.3);
border: 1px solid #ddd;
font-size: 13px;
}
#plyr-control-panel h3 {
margin: 0 0 8px 0;
color: #333;
font-size: 14px;
}
.control-row {
margin-bottom: 8px;
display: flex;
align-items: center;
}
.control-label {
margin-right: 10px;
min-width: 100px;
}
.control-btn {
background: #f0f0f0;
border: 1px solid #ccc;
color: #333;
padding: 3px 8px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
margin-left: 5px;
}
.control-btn:hover {
background: #e0e0e0;
}
.control-checkbox {
margin-right: 5px;
}
.speed-input {
width: 40px;
margin-left: 5px;
}
`);
// 创建浮动控制面板(保持原图风格)
function createControlPanel() {
const panel = document.createElement('div');
panel.id = 'plyr-control-panel';
panel.innerHTML = `
Plyr Controller
Speed:
`;
document.body.appendChild(panel);
// 事件监听
$('#apply-btn').click(applySettings);
$('#reset-btn').click(resetVideo);
}
// 应用设置
function applySettings() {
config.autoSkip = $('#auto-skip').is(':checked');
config.enableSeek = $('#enable-seek').is(':checked');
config.playbackSpeed = parseFloat($('#speed-control').val());
GM_setValue('autoSkip', config.autoSkip);
GM_setValue('enableSeek', config.enableSeek);
GM_setValue('speed', config.playbackSpeed);
if (window.currentPlayer) {
setupPlayerHooks(window.currentPlayer);
}
}
// 重置视频
function resetVideo() {
if (window.currentPlayer) {
window.currentPlayer.currentTime = 0;
window.currentPlayer.play();
}
}
// 核心跳转逻辑(修改为播放时触发)
function setupPlayerHooks(player) {
// 1. 移除原有限制
player.off('ended');
player.off('timeupdate');
// 2. 设置播放速度
player.speed = config.playbackSpeed;
// 3. 启用进度条
if (config.enableSeek) {
player.media.controls = true;
player.media.removeAttribute('controlslist');
$('.plyr__progress').css('display', 'block');
}
// 4. 播放时跳转逻辑(新增)
player.on('play', () => {
if (config.autoSkip) {
setTimeout(() => {
if (player.duration > 0) {
player.currentTime = player.duration - 1;
log('Triggered auto-skip at play event');
} else {
player.on('loadedmetadata', () => {
player.currentTime = player.duration - 1;
});
}
}, config.skipDelay);
}
});
log('Player hooks initialized');
}
// 检测播放器
function detectPlayer() {
const video = document.querySelector('video');
if (video) {
const checkInterval = setInterval(() => {
if (video.plyr) {
clearInterval(checkInterval);
window.currentPlayer = video.plyr;
setupPlayerHooks(video.plyr);
}
}, 500);
}
}
// 初始化
function init() {
createControlPanel();
detectPlayer();
// 监听动态加载
new MutationObserver(detectPlayer).observe(document.body, {
childList: true,
subtree: true
});
}
// 启动
if (document.readyState === 'complete') {
init();
} else {
window.addEventListener('load', init);
}
// 工具函数
function log(message) {
if (config.debugMode) console.log(`[PlyrCtrl] ${message}`);
}
})();