您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
치지직 추가 증폭 볼륨을 구현합니다.
// ==UserScript== // @name 치지직 추가 볼륨 // @namespace 치지직 추가 볼륨 // @match *://chzzk.naver.com/* // @version 0.6 // @description 치지직 추가 증폭 볼륨을 구현합니다. // @icon https://www.google.com/s2/favicons?sz=256&domain_url=chzzk.naver.com // @author mickey90427 <[email protected]> // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const maxVolume = 16; // 최대 볼륨 증폭 비율 let gainValue = getSavedVolume() || 1; // 쿠키에서 저장된 볼륨 값 불러오기, 기본값 1 const originalVolume = 1; let hideTimeout; // 볼륨 증폭 기능 function boostVolume(video, boost) { let audioContext = video.audioContext; let gainNode = video.gainNode; if (!audioContext) { audioContext = new (window.AudioContext || window.webkitAudioContext)(); let source = audioContext.createMediaElementSource(video); gainNode = audioContext.createGain(); source.connect(gainNode); gainNode.connect(audioContext.destination); video.audioContext = audioContext; video.gainNode = gainNode; video.addEventListener('play', () => { audioContext.resume(); }, { once: true }); } gainNode.gain.value = boost ? gainValue : originalVolume; } // 증폭 적용 기능 function applyVolumeBoost() { let videos = document.querySelectorAll('video'); videos.forEach(video => { boostVolume(video, true); }); saveVolume(gainValue); // 볼륨 값 저장 } // 증폭 해제 기능 function removeVolumeBoost() { let videos = document.querySelectorAll('video'); videos.forEach(video => { boostVolume(video, false); }); } // 슬라이더와 버튼을 페이지에 추가 function addVolumeSlider() { const targetElement = document.querySelector('.pzp-pc__bottom-buttons-left'); if (targetElement) { // 기존에 추가된 슬라이더가 있는지 확인 if (document.querySelector('#volumeBoostSlider')) return; const container = document.createElement('div'); container.style.display = 'flex'; container.style.alignItems = 'center'; container.style.marginLeft = '10px'; container.style.opacity = '0'; // 초기에는 숨김 container.style.transition = 'opacity 0.3s'; const slider = document.createElement('input'); slider.id = 'volumeBoostSlider'; slider.type = 'range'; slider.min = 1; slider.max = maxVolume; slider.value = gainValue; slider.style.width = '150px'; slider.style.marginRight = '10px'; slider.style.cursor = 'pointer'; const label = document.createElement('span'); label.id = 'volumeBoostLabel'; label.textContent = `볼륨: ${((gainValue - 1) / (maxVolume - 1) * 100).toFixed(2)}%`; label.style.color = '#fff'; slider.oninput = () => { gainValue = parseFloat(slider.value); const percentage = ((gainValue - 1) / (maxVolume - 1) * 100).toFixed(2); label.textContent = `볼륨: ${percentage}%`; applyVolumeBoost(); // 볼륨 적용 }; container.appendChild(slider); container.appendChild(label); container.id = 'volumeBoostControl'; targetElement.parentNode.insertBefore(container, targetElement.nextSibling); // 슬라이더 표시 및 숨기기 function showSlider() { container.style.opacity = '1'; // 슬라이더 표시 resetHideTimeout(); } function hideSlider() { container.style.opacity = '0'; // 슬라이더 숨김 } function resetHideTimeout() { clearTimeout(hideTimeout); hideTimeout = setTimeout(hideSlider, 3000); // 3초 후 슬라이더 숨김 } // 슬라이더가 있는 요소와 그 하위 요소들에 마우스가 들어가면 슬라이더를 보이게 하고 타이머를 리셋 function setupEventListeners() { const videoContainer = document.querySelector('.webplayer-internal-video'); const shadowElements = document.querySelectorAll('.pzp-pc__bottom-shadow, .pzp-pc__bottom'); function onMouseMoveOrKeyDown(event) { if (videoContainer.contains(event.target) || Array.from(shadowElements).some(el => el.contains(event.target))) { showSlider(); } else { hideSlider(); } } document.addEventListener('mousemove', onMouseMoveOrKeyDown); document.addEventListener('keydown', onMouseMoveOrKeyDown); } setupEventListeners(); } else { console.log('targetElement를 찾을 수 없습니다.'); // 일정 시간 후 재시도 setTimeout(addVolumeSlider, 1000); } } // 쿠키에 볼륨 값 저장 function saveVolume(value) { const domain = window.location.hostname; document.cookie = `volumeBoost_${domain}=${value}; path=/;`; } // 쿠키에서 볼륨 값 불러오기 function getSavedVolume() { const domain = window.location.hostname; const name = `volumeBoost_${domain}=`; const decodedCookie = decodeURIComponent(document.cookie); const cookies = decodedCookie.split(';'); for (let i = 0; i < cookies.length; i++) { let cookie = cookies[i]; while (cookie.charAt(0) === ' ') { cookie = cookie.substring(1); } if (cookie.indexOf(name) === 0) { return parseFloat(cookie.substring(name.length, cookie.length)); } } return null; // 쿠키에 저장된 볼륨 값이 없으면 null 반환 } // 비디오가 로드된 후에 볼륨을 적용하는 함수 function init() { function waitForVideoAndApply() { const videos = document.querySelectorAll('video'); if (videos.length > 0) { applyVolumeBoost(); // 비디오가 존재할 때 볼륨 적용 addVolumeSlider(); // 슬라이더 추가 } else { // 비디오가 없으면 100ms 후에 다시 시도 setTimeout(waitForVideoAndApply, 100); } } waitForVideoAndApply(); // 비디오 로드 확인 후 볼륨 적용 시작 // MutationObserver를 사용하여 새로운 비디오 요소가 추가되었을 때 다시 시도 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length > 0) { waitForVideoAndApply(); // 비디오가 추가되었을 때 볼륨 적용 시도 } }); }); observer.observe(document.body, { childList: true, subtree: true }); } init(); })();