Fix Instagram Videos

Adds controls, prevents auto-mute, disables looping, and stops pause on tab switch

当前为 2025-07-10 提交的版本,查看 最新版本

// ==UserScript==
// @name         Fix Instagram Videos
// @namespace    andreiv
// @version      1.0
// @description  Adds controls, prevents auto-mute, disables looping, and stops pause on tab switch
// @match        https://www.instagram.com/
// @match        https://www.instagram.com/*
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Override muted property globally
    const originalMuted = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'muted');
    Object.defineProperty(HTMLMediaElement.prototype, 'muted', {
        get: function() {
            return false;
        },
        set: function(value) {
            // Always force unmuted
            if (originalMuted && originalMuted.set) {
                originalMuted.set.call(this, false);
            }
        },
        configurable: true
    });

    // Process video elements
    function processVideo(video) {
        // Remove Instagram's overlay
        if (video.nextElementSibling) {
            video.nextElementSibling.remove();
        }

        // Add controls and unmute
        video.controls = true;
        video.muted = false;
        video.volume = 1;

        // Prevent pause on tab switch
        const originalPause = video.pause;
        video.pause = function() {
            if (document.hidden) return;
            return originalPause.call(this);
        };

        // Block autoplay on tab return
        let blockPlay = false;
        const originalPlay = video.play;
        video.play = function() {
            if (blockPlay || this.ended) return Promise.resolve();
            return originalPlay.call(this);
        };

        // When tab becomes visible, block play for 500ms
        document.addEventListener('visibilitychange', () => {
            if (!document.hidden) {
                blockPlay = true;
                setTimeout(() => {
                    blockPlay = false;
                }, 500);
            }
        });

        // Prevent looping by intercepting ended event
        video.addEventListener('ended', (e) => {
            e.stopImmediatePropagation();
            video.pause();
            video.currentTime = video.duration || 0;
        }, true);
    }

    // Watch for new videos
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeName === 'VIDEO') {
                    processVideo(node);
                } else if (node.querySelectorAll) {
                    node.querySelectorAll('video').forEach(processVideo);
                }
            });
        });
    });

    // Start observing
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // Initial run for existing videos
    document.querySelectorAll('video').forEach(processVideo);
})();