Adjusts video playback speed with keyboard shortcuts and shows a temporary UI.
当前为
// ==UserScript==
// @name Universal Video Speed Adjuster
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Adjusts video playback speed with keyboard shortcuts and shows a temporary UI.
// @match *://*/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Set to true to enable debug logs in the console.
const DEBUG_MODE = true;
// Function to create and display the playback rate UI
function displayPlaybackRate(rate) {
// Find if a display element already exists
let displayElement = document.getElementById("playback-rate-display");
if (!displayElement) {
// If not, create a new one
displayElement = document.createElement("div");
displayElement.id = "playback-rate-display";
// Apply styles to the display element
Object.assign(displayElement.style, {
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
backgroundColor: 'rgba(0, 0, 0, 0.7)',
color: 'white',
padding: '10px 15px',
borderRadius: '8px',
fontFamily: 'Inter, sans-serif',
fontSize: '18px',
fontWeight: 'bold',
zIndex: '99999',
opacity: '0',
transition: 'opacity 0.5s ease',
pointerEvents: 'none'
});
document.body.appendChild(displayElement);
}
// Set the new text content and make it visible
displayElement.textContent = `Speed: ${rate.toFixed(2)}x`;
displayElement.style.opacity = '1';
// Clear any existing fade-out timer
clearTimeout(window.playbackRateTimeout);
// Set a new timer to fade the UI out after 2 seconds
window.playbackRateTimeout = setTimeout(() => {
displayElement.style.opacity = '0';
setTimeout(() => {
if (displayElement.parentElement) {
displayElement.parentElement.removeChild(displayElement);
}
}, 500); // Wait for the transition to finish
}, 2000);
}
// Function to find the video element and adjust its speed
function adjustVideoSpeed(adjustment) {
let videoFound = false;
// 1. Check the main document for a video element
const mainVideo = document.getElementsByTagName("video")[0];
if (mainVideo) {
mainVideo.playbackRate = Math.max(0.25, mainVideo.playbackRate + adjustment);
displayPlaybackRate(mainVideo.playbackRate);
videoFound = true;
if (DEBUG_MODE) {
console.log("Video found in the main document. Speed adjusted.");
}
}
// 2. Check all iframes on the page
const iframes = document.getElementsByTagName("iframe");
for (let i = 0; i < iframes.length; i++) {
try {
// Try to access the iframe's contentWindow and document
const iframeDocument = iframes[i].contentWindow.document;
const iframeVideo = iframeDocument.getElementsByTagName("video")[0];
if (iframeVideo) {
iframeVideo.playbackRate = Math.max(0.25, iframeVideo.playbackRate + adjustment);
displayPlaybackRate(iframeVideo.playbackRate);
videoFound = true;
if (DEBUG_MODE) {
console.log("Video found inside an iframe. Speed adjusted.");
}
}
} catch (e) {
// This catch block handles the Same-Origin Policy error
// when we can't access the iframe's content.
if (DEBUG_MODE) {
console.log(`Blocked from accessing iframe due to Same-Origin Policy: ${e.message}`);
}
}
}
if (!videoFound) {
if (DEBUG_MODE) {
console.warn("No video element found to adjust.");
}
}
}
// Attach a keyboard event listener to the entire document
document.addEventListener('keydown', function(event) {
if (DEBUG_MODE) {
console.log(`Keydown event detected: key=${event.key}, code=${event.code}, altKey=${event.altKey}, ctrlKey=${event.ctrlKey}, shiftKey=${event.shiftKey}`);
}
// Check for Option + . (increase speed)
if (event.altKey && event.code === 'Period') {
event.preventDefault(); // Prevents default browser actions
adjustVideoSpeed(0.5);
}
// Check for Option + , (decrease speed)
else if (event.altKey && event.code === 'Comma') {
event.preventDefault(); // Prevents default browser actions
adjustVideoSpeed(-0.5);
}
});
})();