// ==UserScript==
// @name Loud media detector
// @namespace extteen.github.io
// @version 1.0
// @author Extteen
// @description Userscript for detecting loud media, like 'G. Allows resuming and adjusting the threshold.
// @match *://soyjak.st/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
if (window._LOUD_MEDIA_DETECTOR_ACTIVE_) return;
window._LOUD_MEDIA_DETECTOR_ACTIVE_ = true; // i will add this to spe too so i want to prevent double detection or something
const DEFAULT_THRESHOLD = 0.6;
const CHECK_INTERVAL = 50;
let threshold = parseFloat(localStorage.getItem("loudmedia_threshold")) || DEFAULT_THRESHOLD;
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const monitored = new WeakSet();
const allowedMedia = new WeakSet();
function saveThreshold(value) {
threshold = value;
localStorage.setItem("loudmedia_threshold", value);
}
function createOverlay(media, peak) {
if (media.__algOverlay) return;
const overlay = document.createElement("div");
media.__algOverlay = overlay;
overlay.style.position = "absolute";
overlay.style.top = "10px";
overlay.style.left = "10px";
overlay.style.background = "#FF0000";
overlay.style.color = "white";
overlay.style.padding = "10px";
overlay.style.zIndex = 999999;
overlay.style.fontSize = "14px";
overlay.innerHTML = `
Loud audio detected, media paused. Peak: ${peak.toFixed(2)} (limit: ${threshold})
`;
overlay.querySelector("#resume").onclick = () => {
allowedMedia.add(media);
overlay.remove();
media.play();
};
overlay.querySelector("#adjust").onclick = () => {
const input = prompt("Set loudness threshold:", threshold);
if (!input) return;
const value = Math.min(10, Math.max(0.1, parseFloat(input)));
saveThreshold(value);
alert("[Loud media detector userscript] Loud threshold set to: " + value);
overlay.remove();
};
media.parentElement.style.position = "relative";
media.parentElement.appendChild(overlay);
}
function monitorMedia(media) {
if (monitored.has(media)) return;
monitored.add(media);
try {
const source = audioContext.createMediaElementSource(media);
const analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
source.connect(analyser);
analyser.connect(audioContext.destination);
const buffer = new Float32Array(analyser.fftSize);
setInterval(() => {
if (media.paused || media.muted) return;
if (allowedMedia.has(media)) return;
analyser.getFloatTimeDomainData(buffer);
let peak = 0;
for (let i = 0; i < buffer.length; i++) {
const val = Math.abs(buffer[i]);
if (val > peak) peak = val;
}
if (peak > threshold) {
media.pause();
createOverlay(media, peak);
}
}, CHECK_INTERVAL);
} catch (e) {
console.warn("Audio hook failed:", e);
}
}
function scan() {
document.querySelectorAll("video, audio").forEach(monitorMedia);
}
new MutationObserver(scan).observe(document.body, {
childList: true,
subtree: true
});
scan();
document.addEventListener("click", () => {
audioContext.resume();
}, { once: true });
})();