Tab Media Focus (Smart Filter)

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

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==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();
        }
    });

})();