// ==UserScript== // @name Chzzk 선명한 화면 업그레이드 // @description Chzzk 방송에 선명도 필터를 적용하고 UI에서 직접 ON/OFF 및 강도 조절 기능을 제공합니다. // @namespace http://tampermonkey.net/ // @icon https://chzzk.naver.com/favicon.ico // @version 2.0 // @match https://chzzk.naver.com/* // @grant none // @run-at document-idle // @license MIT // @downloadURL none // ==/UserScript== (() => { 'use strict'; // 상수 정의 const STORAGE_KEY_ENABLED = 'chzzkSharpnessEnabled'; const STORAGE_KEY_INTENSITY = 'chzzkSharpnessIntensity'; const FILTER_ID = 'sharpnessFilter'; const SVG_ID = 'sharpnessSVGContainer'; const STYLE_ID = 'sharpnessStyle'; const MENU_SELECTOR = '.pzp-pc__settings'; const FILTER_ITEM_SELECTOR = '.pzp-pc-setting-intro-filter'; class SharpnessFilter extends EventTarget { #enabled = false; #intensity = parseFloat(localStorage.getItem(STORAGE_KEY_INTENSITY)) || 1; #svgContainer; #style; constructor() { super(); this.#svgContainer = this.#createSVG(); this.#style = this.#createStyle(); this.#style.media = 'none'; } get enabled() { return this.#enabled; } get intensity() { return this.#intensity; } #createSVG() { const div = document.createElement('div'); div.id = SVG_ID; div.innerHTML = ` `; return div; } #createStyle() { const style = document.createElement('style'); style.id = STYLE_ID; style.textContent = ` .pzp-pc .webplayer-internal-video { filter: url(#${FILTER_ID}) !important; } .sharp-slider { accent-color: var(--sharp-accent, #ccc); } `; return style; } #updateFilter() { const k = this.#intensity; const off = -((k - 1) / 4); const matrix = `0 ${off} 0 ${off} ${k} ${off} 0 ${off} 0`; this.#svgContainer.querySelector('feConvolveMatrix').setAttribute('kernelMatrix', matrix); } init() { document.body.append(this.#svgContainer); document.head.append(this.#style); this.#updateFilter(); if (localStorage.getItem(STORAGE_KEY_ENABLED) === 'true') this.enable(false); this.dispatchEvent(new Event('initialized')); } enable(persist = true) { if (this.#enabled) return; this.#enabled = true; this.#style.media = 'all'; if (persist) localStorage.setItem(STORAGE_KEY_ENABLED, 'true'); this.dispatchEvent(new Event('enabled')); } disable(persist = true) { if (!this.#enabled) return; this.#enabled = false; this.#style.media = 'none'; if (persist) localStorage.setItem(STORAGE_KEY_ENABLED, 'false'); this.dispatchEvent(new Event('disabled')); } toggle() { this.enabled ? this.disable() : this.enable(); this.dispatchEvent(new Event('toggle')); } setIntensity(value) { this.#intensity = value; this.#updateFilter(); localStorage.setItem(STORAGE_KEY_INTENSITY, String(value)); this.dispatchEvent(new Event('intensitychange')); } } const sharpness = new SharpnessFilter(); sharpness.init(); function addMenuControls(menu) { if (menu.dataset.sharpEnhanceDone) return; menu.dataset.sharpEnhanceDone = 'true'; let container = menu.querySelector(FILTER_ITEM_SELECTOR); if (!container) { container = document.createElement('div'); container.className = 'pzp-ui-setting-home-item'; container.setAttribute('role', 'menuitem'); container.tabIndex = 0; menu.append(container); } container.classList.add('pzp-ui-setting-home-item'); container.innerHTML = `