Fix Instagram Videos

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Fix Instagram Videos
// @namespace    andreiv
// @version      1.1
// @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() {
            // Only block if blockPlay is true (for tab switching)
            if (blockPlay) return Promise.resolve();

            // CRITICAL FIX: Check if we're at the end and reset
            // Firefox doesn't auto-reset currentTime when playing from ended state
            if (this.currentTime >= this.duration - 0.1 || this.ended) {
                this.currentTime = 0;
            }

            return originalPlay.call(this);
        };

        // Also intercept the play event to double-check
        video.addEventListener('play', function(e) {
            // If we're playing but still at the end, force reset
            if (video.currentTime >= video.duration - 0.1) {
                video.currentTime = 0;
            }
        }, true);

        // 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();
            // Don't manipulate currentTime here, let it stay at the end naturally
        }, 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);
})();