Tab Media Focus (Smart Filter)

Pause media in other tabs when playing media in current tab (mobile-like behavior)

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Tab Media Focus (Smart Filter)
// @namespace    https://greasyfork.org/en/scripts/589569/
// @version      1.2
// @description  Pause media in other tabs when playing media in current tab (mobile-like behavior)
// @author       TechComet
// @match        *://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

// Written using Qwen Ai from the first attempt

(function() {
    'use strict';

    // 1. Generate a unique ID for this tab
    const MY_TAB_ID = 'tab_' + Math.random().toString(36).substr(2, 9);
    const STORAGE_KEY = 'active_media_focus_id';

    // 2. Configuration for Smart Filtering
    const CONFIG = {
        ignoreMuted: true,             // Ignore muted videos (common in previews)
        ignoreShortDuration: true,     // Ignore very short videos (previews)
        minDurationSeconds: 5,         // Minimum duration to be considered "real" media
        previewKeywords: [             // Keywords in class names indicating previews
            'preview', 'thumbnail', 'mini', 'hover', 'feed', 'shorts',
            'ytd-thumbnail', 'video-preview', 'autoplay-preview'
        ]
    };

    console.log(`[MediaFocus] Initialized: ${MY_TAB_ID}`);

    // 3. Check if video is a preview/thumbnail based on multiple criteria
    function isPreviewVideo(media) {
        // A. Check Mute Status (Fastest & Most Reliable)
        if (CONFIG.ignoreMuted && (media.muted || media.volume === 0)) {
            return true;
        }

        // B. Check Class Names (Fast)
        if (media.classList) {
            for (let i = 0; i < media.classList.length; i++) {
                const cls = media.classList[i].toLowerCase();
                for (const keyword of CONFIG.previewKeywords) {
                    if (cls.includes(keyword)) {
                        return true;
                    }
                }
            }
        }

        // C. Check Duration (Reliable if metadata loaded)
        if (CONFIG.ignoreShortDuration && media.duration) {
            if (isFinite(media.duration) && media.duration < CONFIG.minDurationSeconds) {
                return true;
            }
        }

        return false;
    }

    // 4. Pause all media elements in this tab
    function pauseAllMedia() {
        const mediaElements = document.querySelectorAll('video, audio');
        let pausedCount = 0;
        mediaElements.forEach(media => {
            if (!media.paused) {
                media.pause();
                pausedCount++;
            }
        });
        if (pausedCount > 0) console.log(`[MediaFocus] Paused ${pausedCount} media element(s)`);
    }

    // 5. Claim focus when valid media starts playing
    function claimFocus() {
        GM_setValue(STORAGE_KEY, MY_TAB_ID);
    }

    // 6. Listen for 'play' events on the window (Capture Phase)
    // This avoids MutationObserver for better performance
    window.addEventListener('play', (event) => {
        const target = event.target;

        // Ensure it's a valid media element
        if (target instanceof HTMLMediaElement) {
            // Apply smart filters
            if (isPreviewVideo(target)) {
                return; // Ignore preview/thumbnail videos
            }

            // Valid media detected, claim focus
            console.log(`[MediaFocus] Valid media play detected`);
            claimFocus();
        }
    }, true); // 'true' enables capture phase

    // 7. Listen for changes from other tabs via shared storage
    GM_addValueChangeListener(STORAGE_KEY, function(key, oldVal, newVal, remote) {
        // If change came from a remote tab and it's not us, pause local media
        if (remote && newVal && newVal !== MY_TAB_ID) {
            console.log(`[MediaFocus] Tab ${newVal} is playing, pausing local media`);
            pauseAllMedia();
        }
    });

})();