Media Stop Visual Alert Window

미디어가 15초 이상 정지되면 별도 창으로 시각 알림 + 정지 시간 표시

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Advertisement:

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

Advertisement:

// ==UserScript==
// @name         Media Stop Visual Alert Window
// @namespace    media-stop-alert-window
// @version      2.4
// @description  미디어가 15초 이상 정지되면 별도 창으로 시각 알림 + 정지 시간 표시
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const STOP_DELAY = 15000;

    let stopTimer = null;
    let wasPlaying = false;
    let alertWindow = null;
    let alertActive = false;
    let stoppedAt = null;

    function formatTime(date) {
        return date.toLocaleTimeString('ko-KR', {
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
        });
    }

    function openAlertWindow() {
        if (alertWindow && !alertWindow.closed) return;

        alertWindow = window.open(
            '',
            'MediaStopAlertWindow',
            'width=460,height=300,left=100,top=100'
        );

        if (!alertWindow) {
            console.warn('팝업이 차단되었습니다.');
            return;
        }

        alertWindow.document.write(`
            <html>
            <head>
                <title>미디어 정지 알림</title>
                <style>
                    body {
                        margin: 0;
                        background: #300;
                        color: white;
                        font-family: sans-serif;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        height: 100vh;
                        text-align: center;
                    }
                    #box {
                        padding: 20px;
                    }
                    .alert {
                        font-size: 34px;
                        font-weight: bold;
                        color: #ff5555;
                        animation: blink 0.8s infinite;
                    }
                    .time {
                        font-size: 20px;
                        margin-top: 14px;
                        color: #ffdada;
                    }
                    .title {
                        font-size: 15px;
                        margin-top: 12px;
                        opacity: 0.85;
                        word-break: break-all;
                    }
                    @keyframes blink {
                        0%, 100% { opacity: 1; }
                        50% { opacity: 0.25; }
                    }
                </style>
            </head>
            <body>
                <div id="box"></div>
            </body>
            </html>
        `);
    }

    function setAlertWindowStopped() {
        openAlertWindow();

        if (!alertWindow || alertWindow.closed) return;

        alertActive = true;

        const stoppedTimeText = stoppedAt ? formatTime(stoppedAt) : '알 수 없음';

        alertWindow.document.title = '⏸ 미디어 정지됨!';
        alertWindow.document.getElementById('box').innerHTML = `
            <div class="alert">미디어 정지됨!</div>
            <p>15초 이상 재생이 재개되지 않았습니다.</p>
            <div class="time">정지된 시간: ${stoppedTimeText}</div>
            <div class="title">정지된 탭: ${document.title}</div>
        `;

        alertWindow.focus();
    }

    function setAlertWindowNormal() {
        alertActive = false;
        stoppedAt = null;

        if (!alertWindow || alertWindow.closed) return;

        alertWindow.close();
        alertWindow = null;
    }

    function getMediaElements() {
        return [...document.querySelectorAll('video, audio')];
    }

    function isAnyMediaPlaying() {
        return getMediaElements().some(media =>
            !media.paused &&
            !media.ended &&
            media.currentTime > 0 &&
            media.readyState > 2
        );
    }

    function startStopTimer() {
        clearTimeout(stopTimer);

        if (!stoppedAt) {
            stoppedAt = new Date();
        }

        stopTimer = setTimeout(() => {
            stopTimer = null;

            if (!isAnyMediaPlaying()) {
                setAlertWindowStopped();
            }
        }, STOP_DELAY);
    }

    function checkMediaState() {
        const playing = isAnyMediaPlaying();

        if (playing) {
            wasPlaying = true;
            clearTimeout(stopTimer);
            stopTimer = null;

            if (alertActive || stoppedAt) {
                setAlertWindowNormal();
            }

            return;
        }

        if (wasPlaying && !playing && !stopTimer && !alertActive) {
            startStopTimer();
        }
    }

    document.addEventListener('play', () => {
        wasPlaying = true;
        clearTimeout(stopTimer);
        stopTimer = null;
        setAlertWindowNormal();
    }, true);

    document.addEventListener('pause', () => {
        if (wasPlaying && !alertActive) {
            startStopTimer();
        }
    }, true);

    document.addEventListener('ended', () => {
        if (wasPlaying && !alertActive) {
            startStopTimer();
        }
    }, true);

    setInterval(checkMediaState, 1000);

})();