Video Autoplay Blocker

Blocks all video autoplay and allowed playback only after user interaction.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Video Autoplay Blocker
// @namespace    VmlkZW8gQXV0b3BsYXkgQmxvY2tlcg
// @version      1.0
// @description  Blocks all video autoplay and allowed playback only after user interaction.
// @author       smed79
// @license      GPLv3
// @icon         https://i25.servimg.com/u/f25/11/94/21/24/stop-v10.png
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // Flag to track user interaction
    let userInteracted = false;

    // Mark videos as user-initiated after interaction
    const markUserInitiated = () => {
        userInteracted = true;
        document.querySelectorAll('video').forEach(v => {
            v.dataset.userInitiated = 'true';
        });
    };

    // Listen for user interaction events
    ['click', 'keydown', 'touchstart'].forEach(evt =>
        window.addEventListener(evt, markUserInitiated, true)
    );

    // Override play() to block autoplay unless user-initiated
    const originalPlay = HTMLMediaElement.prototype.play;
    HTMLMediaElement.prototype.play = function () {
        if (this.tagName === 'VIDEO') {
            const isUserInitiated = userInteracted || this.dataset.userInitiated === 'true';
            if (isUserInitiated) {
                return originalPlay.apply(this, arguments);
            } else {
                console.warn('[Autoplay Blocked]: play() intercepted');
                const p = Promise.resolve();
                p.catch(() => {});
                return p;
            }
        }
        return originalPlay.apply(this, arguments);
    };

    // Check for nearby custom controls
    const hasCustomControlsNearby = (video) => {
        const container = video.closest('div, section, article, body');
        if (!container) return false;

        const keywords = ['play', 'pause', 'btn', 'control', 'icon', 'player'];
        const controlsLike = container.querySelectorAll('button, [role="button"], [class], [id]');

        for (let el of controlsLike) {
            const cls = (el.className || '') + ' ' + (el.id || '');
            const clsLower = cls.toLowerCase();
            if (keywords.some(k => clsLower.includes(k))) {
                return true;
            }
        }

        return false;
    };

    // Block autoplay and ensure controls
    const blockAutoplay = (video) => {
        video.autoplay = false;
        video.muted = false;
        video.removeAttribute('autoplay');
        video.removeAttribute('muted');
        video.preload = 'metadata';
        video.pause();

        const hasNativeControls = video.hasAttribute('controls');
        const hasCustomControls = hasCustomControlsNearby(video);

        if (!hasNativeControls && !hasCustomControls) {
            video.setAttribute('controls', 'true');
        }
    };

    // Process all videos on the page
    const processVideos = () => {
        document.querySelectorAll('video').forEach(blockAutoplay);
    };

    // Run on DOM ready and window load
    document.addEventListener('DOMContentLoaded', processVideos);
    window.addEventListener('load', processVideos);

    // Observe DOM for dynamically added videos
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(m => {
            m.addedNodes.forEach(node => {
                if (node.tagName === 'VIDEO') {
                    blockAutoplay(node);
                } else if (node.querySelectorAll) {
                    node.querySelectorAll('video').forEach(blockAutoplay);
                }
            });
        });
    });

    observer.observe(document.documentElement || document.body, {
        childList: true,
        subtree: true
    });

})();