您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Scroll to adjust volume, middle-click to mute, with overlay + per-site memory on Odysee
// ==UserScript== // @name Odysee Volume Control with Mouse Scroll Wheel (Scroll + Overlay + Memory + Mute) // @namespace violentmonkey-userscripts // @version 1.3 // @description Scroll to adjust volume, middle-click to mute, with overlay + per-site memory on Odysee // @match https://odysee.com/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const CONFIG = { VOLUME_STEP: 0.05, REVERSE_SCROLL: true, // true for macOS natural or inverted scrolling, set it to false for Windows behavior DEFAULT_VOLUME: 0.5, OVERLAY_TIMEOUT: 1500, OVERLAY_POSITIONS: { 'odysee.com': { top: '110px', left: '110px' }, // 'odysee.com': { bottom: '10px', right: '10px' }, } }; const hostname = location.hostname; const volumeKey = `volumeMemory_${hostname}`; let overlay = null; let overlayTimeoutId = null; function clamp(val, min, max) { return Math.min(Math.max(val, min), max); } function createOverlay() { if (overlay) return; overlay = document.createElement('div'); Object.assign(overlay.style, { position: 'fixed', padding: '5px 10px', background: 'rgba(0,0,0,0.7)', color: '#fff', fontSize: '14px', borderRadius: '4px', zIndex: '9999', transition: 'opacity 0.4s ease', opacity: '0', pointerEvents: 'none', }); // Apply per-site overlay position or default to top-left const pos = CONFIG.OVERLAY_POSITIONS[hostname] || { top: '10px', left: '10px' }; Object.assign(overlay.style, pos); document.body.appendChild(overlay); } function showOverlay(text) { createOverlay(); overlay.textContent = text; overlay.style.opacity = '1'; if (overlayTimeoutId) clearTimeout(overlayTimeoutId); overlayTimeoutId = setTimeout(() => overlay.style.opacity = '0', CONFIG.OVERLAY_TIMEOUT); } function saveVolume(volume) { localStorage.setItem(volumeKey, volume.toString()); } function loadVolume() { const v = parseFloat(localStorage.getItem(volumeKey)); return isNaN(v) ? CONFIG.DEFAULT_VOLUME : clamp(v, 0, 1); } function handleWheel(e) { const video = e.currentTarget; const delta = e.deltaY * (CONFIG.REVERSE_SCROLL ? -1 : 1); e.preventDefault(); let newVolume = video.volume; if (delta > 0) newVolume -= CONFIG.VOLUME_STEP; else if (delta < 0) newVolume += CONFIG.VOLUME_STEP; newVolume = clamp(newVolume, 0, 1); if (newVolume > 0 && video.muted) video.muted = false; video.volume = newVolume; saveVolume(newVolume); showOverlay(`Volume: ${Math.round(newVolume * 100)}%`); } function handleMiddleClick(e) { if (e.button !== 1) return; const video = e.currentTarget; e.preventDefault(); video.muted = !video.muted; showOverlay(video.muted ? 'Muted' : `Unmuted (${Math.round(video.volume * 100)}%)`); } function initVideo(video) { if (!video || video.dataset.volumeEnhancerAttached) return; video.addEventListener('wheel', handleWheel, { passive: false }); video.addEventListener('mousedown', handleMiddleClick, true); const savedVolume = loadVolume(); video.volume = savedVolume; if (savedVolume === 0) video.muted = true; video.dataset.volumeEnhancerAttached = 'true'; } function tryAttachToExistingVideos() { const videos = document.querySelectorAll('video'); videos.forEach(initVideo); } function observeForNewVideos() { const observer = new MutationObserver(() => { tryAttachToExistingVideos(); }); observer.observe(document.body, { childList: true, subtree: true, }); } function waitForVideos() { // For sites that dynamically load video const interval = setInterval(() => { const video = document.querySelector('video'); if (video) { clearInterval(interval); tryAttachToExistingVideos(); observeForNewVideos(); } }, 300); } // Start if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', waitForVideos); } else { waitForVideos(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址