Video Speed Adjustment
// ==UserScript== // @name Speed Adjustment // @namespace http://tampermonkey.net/ // @version 2025-02-27 V1.0.1 // @description Video Speed Adjustment // @author SMK // @include * // @license MIT // @icon https://bkimg.cdn.bcebos.com/pic/d043ad4bd11373f0b4cbf3e2ab0f4bfbfaed04d2?x-bce-process=image/format,f_auto/quality,Q_70/resize,m_lfit,limit_1,w_536 // @grant none // ==/UserScript== (function() { 'use strict'; // 等待页面加载完成 window.addEventListener('load', function() { const targetSelector = '#ad-pic,.ad-pic,#ad-overlay'; // 隐藏广告元素 function hideElement() { const element = document.querySelector(targetSelector); if (element) { element.style.display = 'none'; } } // 监听页面变化,确保广告及时移除 const observer = new MutationObserver(hideElement); observer.observe(document.body, { childList: true, subtree: true }); // 初始执行一次 hideElement(); // 保存位置到 localStorage function savePosition(position) { localStorage.setItem('speedControlPosition', JSON.stringify(position)); } // 获取保存的位置,默认为右上角 function getSavedPosition() { const savedPosition = localStorage.getItem('speedControlPosition'); return savedPosition ? JSON.parse(savedPosition) : { top: '30px', right: '5px' }; } // 选择页面上的所有视频元素 function addSpeedControlsToVideos() { var videos = document.querySelectorAll('video'); videos.forEach(function(video) { if (!video.hasAttribute('data-speed-controls')) { // 防止重复添加 var speedContainer = document.createElement('div'); speedContainer.style.position = 'absolute'; const position = getSavedPosition(); speedContainer.style.top = position.top; speedContainer.style.right = position.right; speedContainer.style.zIndex = '1000'; speedContainer.style.backgroundColor = 'rgba(0,0,0,0.5)'; speedContainer.style.color = 'white'; speedContainer.style.padding = '3px'; speedContainer.style.borderRadius = '5px'; speedContainer.style.display = 'flex'; speedContainer.style.flexWrap = 'wrap'; // 使按钮换行 speedContainer.style.alignItems = 'center'; // 垂直居中 speedContainer.style.overflow = 'hidden'; // 确保容器不会超出范围 speedContainer.style.width = '45px'; // 设置容器宽度,以便让按钮能够换行 speedContainer.style.transition = 'width 0.3s ease'; // 宽度动画过渡效果 speedContainer.style.whiteSpace = 'nowrap'; // 防止按钮换行 // 通用按钮样式 const buttonStyle = { backgroundColor: 'rgba(0, 0, 0, 0.7)', color: 'white', border: 'none', padding: '3px 6px', borderRadius: '5px', cursor: 'pointer', fontSize: '14px', margin: '3px', fontFamily: 'Arial, sans-serif', // 统一字体 }; // 创建当前倍速按钮 var currentSpeedButton = document.createElement('button'); currentSpeedButton.innerText = `${video.playbackRate}x`; Object.assign(currentSpeedButton.style, buttonStyle); // 点击当前倍速按钮时,切换到其他倍速 currentSpeedButton.addEventListener('click', function() { const speeds = [0.5, 1.0, 2.0, 2.5, 3.0, 5.0]; let currentIndex = speeds.indexOf(video.playbackRate); if (currentIndex === -1) currentIndex = 1; // 默认到1倍速 // 循环倍速 const nextSpeed = speeds[(currentIndex + 1) % speeds.length]; video.playbackRate = nextSpeed; currentSpeedButton.innerText = `${nextSpeed}x`; // 更新按钮显示的倍速 }); // 添加当前倍速按钮到容器 speedContainer.appendChild(currentSpeedButton); // 播放速度选项按钮 const speeds = [0.5, 1.0, 2.0, 2.5, 3.0, 5.0]; speeds.forEach(function(speed) { var speedButton = document.createElement('button'); speedButton.innerText = `${speed}x`; Object.assign(speedButton.style, buttonStyle); // 使用统一的样式 // 点击按钮时改变播放速度 speedButton.addEventListener('click', function() { const wasPaused = video.paused; // 记录视频是否暂停 const wasPlaying = !wasPaused; // 设置播放速度 video.playbackRate = speed; currentSpeedButton.innerText = `${speed}x`; // 更新当前倍速按钮显示的倍速 // 通过 requestAnimationFrame 确保播放不会中断 requestAnimationFrame(() => { if (wasPlaying) { video.play(); } }); }); // 初始时隐藏其他按钮 speedButton.style.display = 'none'; // 关键修改:初始时隐藏 speedContainer.appendChild(speedButton); // 将按钮添加到容器中 }); // 鼠标悬停时展开按钮,鼠标移开时收缩 speedContainer.addEventListener('mouseenter', function() { const buttons = speedContainer.querySelectorAll('button'); buttons.forEach(button => button.style.display = 'block'); // 显示所有按钮 speedContainer.style.width = '270px'; // 扩展容器宽度,显示更多按钮 }); speedContainer.addEventListener('mouseleave', function() { const buttons = speedContainer.querySelectorAll('button'); buttons.forEach((button, index) => { if (index !== 0) button.style.display = 'none'; // 只保留第一个按钮(当前倍速) }); speedContainer.style.width = '45px'; // 恢复容器宽度 }); /** // 创建悬浮窗) **/ const floatingWindow = document.createElement('div'); floatingWindow.style.position = 'absolute'; floatingWindow.style.top = '150px'; floatingWindow.style.right = '-10px'; floatingWindow.style.zIndex = '1000'; floatingWindow.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; floatingWindow.style.padding = '15px'; floatingWindow.style.borderRadius = '15px'; floatingWindow.style.transition = 'opacity 0.3s ease'; floatingWindow.style.opacity = '0.3'; // 鼠标悬停显示按钮 floatingWindow.addEventListener('mouseenter', function() { floatingWindow.style.opacity = '1'; positionButtons.forEach(button => button.style.display = 'block'); }); // 鼠标移出隐藏按钮 floatingWindow.addEventListener('mouseleave', function() { floatingWindow.style.opacity = '0.3'; positionButtons.forEach(button => button.style.display = 'none'); }); const positions = [ { label: '左上', top: '10px', left: '10px' }, { label: '右上', top: '10px', right: '10px' }, { label: '左下', bottom: '10px', left: '10px' }, { label: '右下', bottom: '10px', right: '10px' } ]; const positionButtons = []; positions.forEach(position => { const positionButton = document.createElement('button'); positionButton.innerText = position.label; Object.assign(positionButton.style, buttonStyle); positionButton.style.display = 'none'; positionButton.style.marginBottom = '5px'; positionButton.addEventListener('click', function() { speedContainer.style.top = position.top || ''; speedContainer.style.right = position.right || ''; speedContainer.style.bottom = position.bottom || ''; speedContainer.style.left = position.left || ''; savePosition(position); }); floatingWindow.appendChild(positionButton); positionButtons.push(positionButton); }); // 将按钮容器插入到视频元素之前 video.parentNode.insertBefore(speedContainer, video); video.parentNode.insertBefore(floatingWindow, video); video.setAttribute('data-speed-controls', 'true'); // 防止重复添加 } }); } // 创建 MutationObserver 监听 video 元素的变化 const videoObserver = new MutationObserver(addSpeedControlsToVideos); videoObserver.observe(document.body, { childList: true, subtree: true }); // 初始执行一次 addSpeedControlsToVideos(); }); })();