// ==UserScript== // @name 按住 ; 键倍速播放(支持音频) // @namespace http://tampermonkey.net/ // @version 1.3 // @description 按住 L 键或 ; 键时视频/音频倍速播放,松开恢复原速 // @author 白鹭 & 优化版 // @match *://*/* // @grant none // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/574591/%E6%8C%89%E4%BD%8F%20%3B%20%E9%94%AE%E5%80%8D%E9%80%9F%E6%92%AD%E6%94%BE%EF%BC%88%E6%94%AF%E6%8C%81%E9%9F%B3%E9%A2%91%EF%BC%89.user.js // @updateURL https://update.greasyfork.icu/scripts/574591/%E6%8C%89%E4%BD%8F%20%3B%20%E9%94%AE%E5%80%8D%E9%80%9F%E6%92%AD%E6%94%BE%EF%BC%88%E6%94%AF%E6%8C%81%E9%9F%B3%E9%A2%91%EF%BC%89.meta.js // ==/UserScript== (function() { 'use strict'; // 配置 const SPEED_KEY = ';'; // 触发键(; 键,通常与 L 键同键位但需 Shift,这里直接匹配按键值) const PLAYBACK_RATE = 3.0; // 倍速 const DEFAULT_RATE = 1.0; // 原速 let activeMedia = null; // 当前激活的媒体元素(video 或 audio) let isHolding = false; // 是否按住按键 /** * 查找页面上的媒体元素(优先 video,其次 audio) * 策略:优先返回当前正在播放或有焦点的元素,否则返回第一个找到的媒体元素 * @returns {HTMLMediaElement|null} */ function findMediaElement() { // 优先检查当前有焦点的元素是否为媒体元素 const focused = document.activeElement; if (focused && (focused.tagName === 'VIDEO' || focused.tagName === 'AUDIO')) { return focused; } // 查找所有视频和音频元素 const mediaElements = Array.from(document.querySelectorAll('video, audio')); // 优先选择正在播放的媒体 const playing = mediaElements.find(media => !media.paused && !media.ended); if (playing) return playing; // 返回第一个可用的媒体元素 return mediaElements[0] || null; } /** * 设置媒体元素的播放速度 * @param {HTMLMediaElement} media - 媒体元素 * @param {number} rate - 倍速值 */ function setMediaSpeed(media, rate) { if (media && media.playbackRate !== rate) { media.playbackRate = rate; console.log(`[媒体倍速] 元素: ${media.tagName}, 速度: ${rate}x`); } } // 按键按下事件 function onKeyDown(e) { if (e.repeat) return; // 忽略按住时自动重复触发的事件 // 检查按下的键是否为配置的键(忽略大小写,并处理实际按键值) if (e.key !== SPEED_KEY && e.key !== ';') return; // 兼容某些浏览器返回 ';' 或 ';' 的表示 // 如果当前焦点在输入框或文本域中,不触发倍速 const tagName = e.target.tagName; if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') { return; } isHolding = true; activeMedia = findMediaElement(); if (activeMedia) { setMediaSpeed(activeMedia, PLAYBACK_RATE); } } // 按键松开事件 function onKeyUp(e) { if (e.key !== SPEED_KEY && e.key !== ';') return; isHolding = false; if (activeMedia) { setMediaSpeed(activeMedia, DEFAULT_RATE); activeMedia = null; } } // 页面失去焦点时,如果还按着键,则恢复原速 function onBlur() { if (activeMedia && isHolding) { setMediaSpeed(activeMedia, DEFAULT_RATE); } isHolding = false; activeMedia = null; } // 监听键盘事件和窗口失焦 document.addEventListener('keydown', onKeyDown); document.addEventListener('keyup', onKeyUp); window.addEventListener('blur', onBlur); // 可选:监听动态添加的媒体元素(无需额外处理,但保留 MutationObserver 以维持原有结构) const observer = new MutationObserver(() => { // 媒体元素变化时无需特殊操作,因为每次按键都会重新查找 }); observer.observe(document.body, { childList: true, subtree: true }); console.log('[媒体倍速脚本] 已加载 - 按住 ; 键倍速播放(支持视频和音频)'); })();