您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
soop 방송 딜레이 약 1초로 자동 조정 - 변경가능
当前为
// ==UserScript== // @name soop 방송 딜레이 자동 조정 // @namespace https://greasyfork.org/ko/scripts/539405 // @version 1.1 // @description soop 방송 딜레이 약 1초로 자동 조정 - 변경가능 // @icon https://www.google.com/s2/favicons?sz=64&domain=www.sooplive.co.kr // @author 다크초코 // @match https://play.sooplive.co.kr/* // @match https://vod.sooplive.co.kr/* // @license MIT // ==/UserScript== (function() { 'use strict'; const CONFIG = { CHECK_INTERVAL: 100, // 딜레이 체크 간격 (ms) HISTORY_DURATION: 2000, // 평균 계산 기간 (ms) - 최근 2000ms동안 계산된 딜레이의 평균값을 기준으로 딜레이 조정 TRIGGER_DELAY: 1500, // 자동 조정 시작 딜레이 (ms) - 2500ms 도달시 조절 시작(튀는 딜레이 값 방지) TARGET_DELAY: 1000, // 목표 딜레이 (ms) - 시작 딜레이보다 500ms이상 더 짧게 설정 추천 SPEED_LEVELS: [ { minDelay: 5000, playbackRate: 1.3 }, // 5초 이상 - 1.3배 { minDelay: 3000, playbackRate: 1.25 }, // 3초 이상 - 1.25배 { minDelay: 2500, playbackRate: 1.2 }, // 2.5초 이상 - 1.2배 { minDelay: 2000, playbackRate: 1.15 }, // 2초 이상 - 1.15배 { minDelay: 1500, playbackRate: 1.1 }, // 1.5초 이상 - 1.1배 { minDelay: 0, playbackRate: 1.05 } // 그 외 - 1.05배 ], NORMAL_RATE: 1.0 // 정상 재생 속도 }; let delayHistory = []; let isAdjusting = false; let checkInterval = null; let video = null; let currentPlaybackRate = 1.0; function findVideo() { return document.querySelector('video'); } function calculateDelay(videoElement) { if (!videoElement) return null; const buffered = videoElement.buffered; if (buffered.length > 0) { const bufferedEnd = buffered.end(buffered.length - 1); const currentTime = videoElement.currentTime; const delay = bufferedEnd - currentTime; return delay >= 0 ? delay * 1000 : null; } return null; } function addDelayToHistory(delay) { const now = Date.now(); delayHistory.push({ delay, timestamp: now }); delayHistory = delayHistory.filter(item => now - item.timestamp <= CONFIG.HISTORY_DURATION ); } function getAverageDelay() { if (delayHistory.length === 0) return 0; const totalDelay = delayHistory.reduce((sum, item) => sum + item.delay, 0); return totalDelay / delayHistory.length; } function getPlaybackRate(averageDelay) { for (const config of CONFIG.SPEED_LEVELS) { if (averageDelay >= config.minDelay) { return config.playbackRate; } } return CONFIG.SPEED_LEVELS[CONFIG.SPEED_LEVELS.length - 1].playbackRate; } function adjustPlaybackRate(rate) { if (video && video.playbackRate !== rate) { video.playbackRate = rate; currentPlaybackRate = rate; } } function displayDelayInfo(currentDelay, averageDelay) { let infoElement = document.getElementById('delay-info'); if (!infoElement) { infoElement = document.createElement('div'); infoElement.id = 'delay-info'; infoElement.style.cssText = ` position: fixed; bottom: 10px; right: 10px; background: rgba(0, 0, 0, 0.7); color: white; padding: 3px 5px; border-radius: 3px; font-family: monospace; font-size: 7pt; line-height: 1.2; z-index: 10000; opacity: 0.8; `; document.body.appendChild(infoElement); } const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; infoElement.style.display = isFullscreen ? 'none' : 'block'; const status = isAdjusting ? `${currentPlaybackRate}x` : '1.0x'; infoElement.innerHTML = `${averageDelay.toFixed(0)}ms ${status}`; } function setupFullscreenListener() { const events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange']; events.forEach(event => { document.addEventListener(event, () => { const infoElement = document.getElementById('delay-info'); if (infoElement) { const isFullscreen = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; infoElement.style.display = isFullscreen ? 'none' : 'block'; } }); }); } function checkAndAdjustDelay() { if (!video) { video = findVideo(); if (!video) return; } const currentDelay = calculateDelay(video); if (currentDelay === null) return; addDelayToHistory(currentDelay); const averageDelay = getAverageDelay(); displayDelayInfo(currentDelay, averageDelay); if (delayHistory.length < 10) return; if (!isAdjusting && averageDelay >= CONFIG.TRIGGER_DELAY) { isAdjusting = true; const playbackRate = getPlaybackRate(averageDelay); adjustPlaybackRate(playbackRate); } else if (isAdjusting && averageDelay <= CONFIG.TARGET_DELAY) { isAdjusting = false; adjustPlaybackRate(CONFIG.NORMAL_RATE); } else if (isAdjusting) { const newPlaybackRate = getPlaybackRate(averageDelay); if (newPlaybackRate !== currentPlaybackRate) { adjustPlaybackRate(newPlaybackRate); } } } function startDelayAdjuster() { video = findVideo(); if (!video) { setTimeout(startDelayAdjuster, 1000); return; } if (checkInterval) { clearInterval(checkInterval); } checkInterval = setInterval(checkAndAdjustDelay, CONFIG.CHECK_INTERVAL); setupFullscreenListener(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startDelayAdjuster); } else { startDelayAdjuster(); } let currentUrl = location.href; const urlObserver = new MutationObserver(() => { if (location.href !== currentUrl) { currentUrl = location.href; if (checkInterval) { clearInterval(checkInterval); checkInterval = null; } delayHistory = []; isAdjusting = false; video = null; currentPlaybackRate = 1.0; setTimeout(startDelayAdjuster, 1000); } }); urlObserver.observe(document, { subtree: true, childList: true }); window.addEventListener('beforeunload', () => { if (checkInterval) { clearInterval(checkInterval); } urlObserver.disconnect(); }); })();