您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Z原速/X减速/C加速(分段步进,支持0.2x),播放器左下角提示 + 屏蔽YouTube字幕快捷键
当前为
// ==UserScript== // @name B站/Youtube 倍速快捷键(Z/X/C) // @version 1.0 // @description Z原速/X减速/C加速(分段步进,支持0.2x),播放器左下角提示 + 屏蔽YouTube字幕快捷键 // @author 重音(support by GPT) // @match https://www.bilibili.com/* // @match https://www.youtube.com/* // @grant GM_setValue // @grant GM_getValue // @license GPL // @namespace https://greasyfork.org/users/1476609 // ==/UserScript== (function () { "use strict"; let isActive = 1; let video = null; let currentRate = GM_getValue("a", 10); // 初始播放速度(单位:10 表示 1.0x) let lastRate = GM_getValue("b", 10); // 上次非 1.0 的倍速 function updateVideoElement() { video = document.querySelector("video") || document.querySelector("bwp-video"); } function setupFocusHandlers() { const inputs = [ document.querySelector(".reply-box-textarea"), document.querySelector(".bpx-player-dm-input"), document.querySelector(".nav-search-input") ]; inputs.forEach(input => { if (input) { input.addEventListener("focus", () => isActive = 0); input.addEventListener("blur", () => isActive = 1); } }); } window.addEventListener("load", () => { updateVideoElement(); setupFocusHandlers(); }); new MutationObserver(() => { updateVideoElement(); setupFocusHandlers(); }).observe(document.body, { childList: true, subtree: true }); setInterval(() => { if (video) { video.playbackRate = currentRate / 10; } }, 600); // 创建气泡提示 const tip = document.createElement("div"); tip.style.cssText = ` position: absolute; left: 10px; bottom: 10px; background: rgba(0, 0, 0, 0.75); color: #fff; padding: 6px 12px; border-radius: 8px; font-size: 14px; z-index: 99999; opacity: 0; transition: opacity 0.3s; pointer-events: none; `; function attachTipToPlayer() { const player = document.querySelector(".bpx-player-container") || document.querySelector(".html5-video-player") || document.querySelector("video")?.parentElement; if (player && player.appendChild && !tip.parentElement) { if (getComputedStyle(player).position === "static") { player.style.position = "relative"; } player.appendChild(tip); } } attachTipToPlayer(); setInterval(attachTipToPlayer, 1000); let tipTimer = null; function showTip(text) { tip.textContent = text; tip.style.opacity = "1"; clearTimeout(tipTimer); tipTimer = setTimeout(() => { tip.style.opacity = "0"; }, 1200); } // 获取当前播放速率下应使用的步进值 function getStep(rate10) { const real = rate10 / 10; if (real < 2) return 2; // 0.2x~2.0x:±0.2 if (real < 4) return 5; // 2.0x~4.0x:±0.5 return 10; // 4.0x~8.0x:±1.0 } // 快捷键监听(捕获阶段) document.addEventListener("keydown", function (e) { if (!isActive) return; const key = e.code; const isYoutube = location.hostname.includes("youtube.com"); // 屏蔽 YouTube C 字幕快捷键 if (isYoutube && key === "KeyC") { e.stopImmediatePropagation(); e.preventDefault(); } if (!video) return; currentRate = Math.round(10 * video.playbackRate); const step = getStep(currentRate); let changed = false; if (key === "KeyX") { e.preventDefault(); currentRate -= step; changed = true; } else if (key === "KeyC") { e.preventDefault(); currentRate += step; changed = true; } else if (key === "KeyZ") { e.preventDefault(); currentRate = video.playbackRate === 1.0 ? lastRate : 10; changed = true; } else if (key === "KeyF") { if (document.fullscreenElement) { document.exitFullscreen(); } else { document.documentElement.requestFullscreen(); } } // 限制播放速率范围(最小 0.2x,最大 8.0x) currentRate = Math.max(2, Math.min(currentRate, 80)); if (changed) { GM_setValue("a", currentRate); if (key !== "KeyZ") { lastRate = currentRate; GM_setValue("b", lastRate); } video.playbackRate = currentRate / 10; showTip(`播放速度:${(currentRate / 10).toFixed(1)}x`); } }, true); // 同步 B站倍速面板显示的值 setInterval(() => { const rateDisplay = document.querySelector(".bpx-player-ctrl-playbackrate-result"); if (rateDisplay) { const val = parseFloat(rateDisplay.textContent.replace("x", "")); if (!isNaN(val)) { currentRate = Math.round(val * 10); GM_setValue("a", currentRate); } } }, 2000); })();