您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
视频播放增强:1. 长按左键临时加速 2. B站自动开启AI字幕
当前为
// ==UserScript== // @name 视频控制增强 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 视频播放增强:1. 长按左键临时加速 2. B站自动开启AI字幕 // @author Alonewinds // @match *://*/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @run-at document-start // @license MIT // ==/UserScript== (function() { 'use strict'; // ================ 通用配置和工具函数 ================ const config = { speedRate: GM_getValue('speedRate', 2.0), minPressTime: 200, selectors: { 'www.bilibili.com': '.bilibili-player-video-control-wrap, .squirtle-controller-wrap', 'www.youtube.com': '.ytp-chrome-bottom, .ytp-progress-bar', 'default': '.video-controls, .progress-bar, [role="slider"]' } }; // ================ 倍速控制功能 ================ let pressStartTime = 0; let originalSpeed = 1.0; let isPressed = false; let activeVideo = null; let isLongPress = false; let preventNextClick = false; // 注册倍速设置菜单 GM_registerMenuCommand('设置倍速值', () => { const newSpeed = prompt('请输入新的倍速值(建议范围:1.1-4):', config.speedRate); if (newSpeed && !isNaN(newSpeed)) { config.speedRate = parseFloat(newSpeed); GM_setValue('speedRate', config.speedRate); } }); function findVideoElement(element) { if (!element) return null; if (element instanceof HTMLVideoElement) { return element; } const domain = window.location.hostname; const controlSelector = config.selectors[domain] || config.selectors.default; if (element.closest(controlSelector)) { return null; } if (domain === 'www.youtube.com') { const ytPlayer = element.closest('.html5-video-player'); return ytPlayer ? ytPlayer.querySelector('video') : null; } const container = element.closest('*:has(video)'); const video = container?.querySelector('video'); return video && window.getComputedStyle(video).display !== 'none' ? video : null; } function setYouTubeSpeed(video, speed) { if (window.location.hostname === 'www.youtube.com') { const player = video.closest('.html5-video-player'); if (player) { try { video.playbackRate = speed; const moviePlayer = player.querySelector('.video-stream'); if (moviePlayer) { moviePlayer.playbackRate = speed; } video.dispatchEvent(new Event('ratechange')); } catch (e) { console.error('设置 YouTube 播放速度失败:', e); } } } else { video.playbackRate = speed; } } // ================ B站字幕功能 ================ let subtitleEnabled = false; let subtitleAttempts = 0; let subtitleRetryTimer = null; let manuallyDisabled = false; let currentVideoId = ''; let clickHandler = null; function getVideoId() { const match = location.pathname.match(/\/video\/(.*?)\//); return match ? match[1] : ''; } function enableSubtitle() { if (window.location.hostname !== 'www.bilibili.com') return; if (subtitleAttempts >= 5 || manuallyDisabled) return; subtitleAttempts++; const button = document.querySelector("div.bpx-player-ctrl-btn.bpx-player-ctrl-subtitle > div.bpx-player-ctrl-btn-icon > span"); if (!button) { subtitleRetryTimer = setTimeout(enableSubtitle, 1000); return; } const parent = button.closest('.bpx-player-ctrl-subtitle'); if (!parent) return; if (clickHandler) { parent.removeEventListener('click', clickHandler); } clickHandler = (event) => { requestAnimationFrame(() => { if (!parent.classList.contains('bpx-player-ctrl-subtitle-on')) { manuallyDisabled = true; console.log('用户已手动关闭字幕,本视频将不再自动开启'); } }); }; parent.addEventListener('click', clickHandler); if (!parent.classList.contains('bpx-player-ctrl-subtitle-on') && !manuallyDisabled) { button.click(); subtitleEnabled = true; } } // ================ 事件处理 ================ function handleMouseDown(e) { if (e.button !== 0) return; const video = findVideoElement(e.target); if (!video) return; pressStartTime = Date.now(); activeVideo = video; originalSpeed = window.location.hostname === 'www.youtube.com' ? (video.closest('.html5-video-player').querySelector('.video-stream')?.playbackRate || video.playbackRate) : video.playbackRate; isPressed = true; isLongPress = false; preventNextClick = false; } function handleMouseUp(e) { if (!isPressed || !activeVideo) return; const pressDuration = Date.now() - pressStartTime; if (pressDuration >= config.minPressTime) { preventNextClick = true; setYouTubeSpeed(activeVideo, originalSpeed); } isPressed = false; isLongPress = false; activeVideo = null; } function handlePressDetection() { if (!isPressed || !activeVideo) return; const pressDuration = Date.now() - pressStartTime; if (pressDuration >= config.minPressTime) { if (activeVideo.playbackRate !== config.speedRate) { setYouTubeSpeed(activeVideo, config.speedRate); } isLongPress = true; } } function handleClick(e) { if (preventNextClick) { e.stopPropagation(); preventNextClick = false; return; } } function onVideoLoad() { if (window.location.hostname !== 'www.bilibili.com') return; const video = document.querySelector('video'); if (!video) { setTimeout(onVideoLoad, 500); return; } function reset() { const newVideoId = getVideoId(); if (newVideoId !== currentVideoId) { manuallyDisabled = false; currentVideoId = newVideoId; if (clickHandler) { const oldButton = document.querySelector('.bpx-player-ctrl-subtitle'); if (oldButton) { oldButton.removeEventListener('click', clickHandler); } clickHandler = null; } } subtitleEnabled = false; subtitleAttempts = 0; if (subtitleRetryTimer) { clearTimeout(subtitleRetryTimer); subtitleRetryTimer = null; } if (!manuallyDisabled) { setTimeout(enableSubtitle, 500); } } video.addEventListener('loadeddata', reset); video.addEventListener('play', () => { if (!subtitleEnabled && !manuallyDisabled) { reset(); } }); reset(); } // ================ 初始化 ================ function initializeEvents() { // 倍速控制事件 document.addEventListener('mousedown', handleMouseDown, true); document.addEventListener('mouseup', handleMouseUp, true); document.addEventListener('click', handleClick, true); document.addEventListener('mouseleave', handleMouseUp, true); function checkPress() { handlePressDetection(); requestAnimationFrame(checkPress); } checkPress(); // B站字幕功能初始化 if (window.location.hostname === 'www.bilibili.com') { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', onVideoLoad); } else { onVideoLoad(); } } } initializeEvents(); })();