// ==UserScript==
// @name 影片音量增強器
// @version 0.0.30
// @author HentaiSaru
// @description 增強影片音量上限,最高增幅至 10 倍,尚未測試是否所有網域都可使用,當影片無聲時,禁止該腳本在該網域上運行。
// @match *://*/*
// @exclude *://video.eyny.com/*
// @icon https://cdn-icons-png.flaticon.com/512/8298/8298181.png
// @license MIT
// @namespace https://greasyfork.org/users/989635
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// ==/UserScript==
(function(){if(/^(http|https):\/\/(?!chrome\/|about\/).*$/i.test(document.URL)){class l{constructor(){this.addlistener=async(a,d,c,b={})=>{a.addEventListener(d,c,b)};this.Menu=async a=>{for(const [d,c]of Object.entries(a))GM_registerMenuCommand(d,()=>{c()})}}$$(a,d=!1,c=document){if(d)return c.querySelectorAll(a);d=a.slice(1);switch(d.includes(" ")||d.includes(".")||d.includes("#")?" ":a[0]){case "#":return c.getElementById(d);case " ":return c.querySelector(a);case ".":return c.getElementsByClassName(d)[0];default:return c.getElementsByTagName(a)[0]}}
store(a,d,c=null){return{__verify:b=>void 0!==b?b:null,set:function(b,e){return GM_setValue(b,e)},get:function(b,e){return this.__verify(GM_getValue(b,e))},setjs:function(b,e){return GM_setValue(b,JSON.stringify(e,null,4))},getjs:function(b,e){return JSON.parse(this.__verify(GM_getValue(b,e)))}}[a](d,c)}}class m extends l{constructor(){super();this.Increase=this.Booster=null;this.Domain=location.hostname;this.EnabledDomains=this.store("get","\u555f\u7528\u7db2\u57df",[]);
this.EnabledStatus=this.EnabledDomains.includes(this.Domain);this.Useboost=async a=>{this.EnabledStatus?(this.EnabledDomains=this.EnabledDomains.filter(d=>d!==a),alert("\u274c \u7981\u7528\u81ea\u52d5\u589e\u5e45")):(this.EnabledDomains.push(a),alert("\u2705 \u555f\u7528\u81ea\u52d5\u589e\u5e45"));this.store("set","\u555f\u7528\u7db2\u57df",this.EnabledDomains);location.reload()};this.MenuHotkey=()=>{this.addlistener(document,"keydown",a=>{a.altKey&&"b"===a.key&&this.IncrementalSetting()},{passive:!0,capture:!0})}}
async Injection(){let a;(new MutationObserver(()=>{(a=this.$$("video"))&&!a.hasAttribute("Video-Audio-Booster")&&this.FindVideo(a)})).observe(document.head,{childList:!0,subtree:!0})}async FindVideo(a){try{this.Increase=this.EnabledStatus?this.store("get",this.Domain)||1:1,this.Booster=this.BoosterLogic(a,this.Increase),GM_addStyle(".Booster-Modal-Background{top:0;left:0;width:100%;height:100%;display:flex;z-index:9999;overflow:auto;position:fixed;align-items:center;justify-content:center;}.Booster-Modal-Button {top: 0;margin: 3% 2%;color: #d877ff;font-size: 16px;font-weight: bold;border-radius: 3px;background-color: #ffebfa;border: 1px solid rgb(124, 183, 252);}.Booster-Modal-Button:hover,.Booster-Modal-Button:focus {color: #fc0e85;cursor: pointer;text-decoration: none;}.Booster-Modal-Content {width: 400px;padding: 5px;overflow: auto;background-color: #cff4ff;border-radius: 10px;text-align: center;border: 2px ridge #82c4e2;border-collapse: collapse;margin: 2% auto 8px auto;}.Booster-Multiplier {font-size:25px;color:rgb(253, 1, 85);margin: 10px;font-weight:bold;}.Booster-Slider {width: 350px;}div input {cursor: pointer;}"),
this.MenuHotkey(),this.Menu({"\ud83d\udd0a [\u958b\u95dc] \u81ea\u52d5\u589e\u5e45":()=>this.Useboost(this.Domain),"\ud83d\udee0\ufe0f \u8a2d\u7f6e\u589e\u5e45":()=>this.IncrementalSetting(),"\ud83d\udcdc \u83dc\u55ae\u71b1\u9375":()=>alert("\u71b1\u9375\u547c\u53eb\u8abf\u6574\u83dc\u55ae!!\n\n\u5feb\u6377\u7d44\u5408 : (Alt + B)")})}catch{}}BoosterLogic(a,d){const c=new window.AudioContext,b=c.createMediaElementSource(a),e=c.createGain(),g=c.createBiquadFilter(),h=c.createBiquadFilter(),f=c.createDynamicsCompressor();a.volume=1;e.gain.value=d*d;f.ratio.value=6;f.knee.value=.5;f.threshold.value=-14;f.attack.value=.02;f.release.value=.4;g.frequency.value=250;g.type="lowshelf";g.gain.value=2.2;h.frequency.value=1E4;h.type="highshelf";h.gain.value=1.8;b.connect(e);e.connect(g);g.connect(h);e.connect(f);f.connect(c.destination);a.setAttribute("Video-Audio-Booster",!0);return{setVolume:function(k){e.gain.value=k*k;this.Increase=k}}}async IncrementalSetting(){if(!this.$$(".Booster-Modal-Background")){const a=document.createElement("div");
a.innerHTML=`<div class="Booster-Modal-Background"><div class="Booster-Modal-Content"><h2 style="color: #3754f8;">\u97f3\u91cf\u589e\u5f37</h2><div style="margin:1rem auto 1rem auto;"><div class="Booster-Multiplier"><span><img src="https://cdn-icons-png.flaticon.com/512/8298/8298181.png" width="5%">\u589e\u5f37\u500d\u6578 </span><span id="CurrentValue">${this.Increase}</span><span> \u500d</span></div><input type="range" id="sound-amplification" class="Booster-Slider" min="0" max="10.0" value="${this.Increase}" step="0.1"><br></div><div style="text-align: right;"><button class="Booster-Modal-Button" id="sound-save">\u4fdd\u5b58\u8a2d\u7f6e</button><button class="Booster-Modal-Button" id="sound-close">\u9000\u51fa\u9078\u55ae</button></div></div></div>`;
document.body.appendChild(a);const d=this.$$("#CurrentValue"),c=this.$$("#sound-amplification");this.addlistener(c,"input",b=>{b=b.target.value;d.textContent=b;this.Booster.setVolume(b)},{passive:!0,capture:!0});this.addlistener(this.$$(".Booster-Modal-Background"),"click",b=>{b.stopPropagation();b=b.target;"sound-save"===b.id?this.EnabledStatus?(this.Increase=b=parseFloat(c.value),this.store("set",this.Domain,b),this.$$(".Booster-Modal-Background").remove()):alert("\u9700\u555f\u7528\u81ea\u52d5\u589e\u5e45\u624d\u53ef\u4fdd\u5b58"):"Booster-Modal-Background"!==b.className&&"sound-close"!==b.id||this.$$(".Booster-Modal-Background").remove()},{capture:!0})}}}(new m).Injection()}})();