iOS Video Force Inline Playback

Force all iOS web videos to play inline using playsinline attribute.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         iOS Video Force Inline Playback
// @name:zh-CN   iOS 网页视频强制内嵌播放
// @namespace    https://greasyfork.org/users/1603433
// @version      1.4
// @description  Force all iOS web videos to play inline using playsinline attribute.
// @description:zh-CN 强制所有 iOS 网页视频使用 playsinline 内嵌播放
// @author       Dason
// @license      MIT
// @match        *://*/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 核心处理函数:强注内嵌属性
    function forceInline(video) {
        if (!video || video.dataset.inlineForced) return;

        video.playsInline = true;
        video.webkitPlaysInline = true;
        
        video.setAttribute('playsinline', 'true');
        video.setAttribute('webkit-playsinline', 'true');
        video.setAttribute('x5-playsinline', 'true'); 
        
        video.dataset.inlineForced = 'true';
    }

    // ================= 原型链劫持 =================
    try {
        // 劫持 play 方法:确保那些通过 JS 动态创建、还没放入 DOM 树就直接播放的视频被注入 playsinline
        const originalPlay = HTMLVideoElement.prototype.play;
        HTMLVideoElement.prototype.play = function() {
            forceInline(this);
            return originalPlay.apply(this, arguments);
        };
    } catch (e) {
        console.error("[InlineVideo] Prototype hijack failed: ", e);
    }

    // ================= DOM 监听 =================
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            mutation.addedNodes.forEach((node) => {
                if (node.tagName === 'VIDEO') {
                    forceInline(node);
                } else if (node.querySelectorAll) {
                    const videos = node.querySelectorAll('video');
                    if (videos.length > 0) videos.forEach(forceInline);
                }
            });
        }
    });

    if (document.documentElement) {
        observer.observe(document.documentElement, { childList: true, subtree: true });
    } else {
        document.addEventListener('DOMContentLoaded', () => {
            observer.observe(document.body, { childList: true, subtree: true });
        });
    }

    // ================= 定时器兜底 =================
    setInterval(() => {
        document.querySelectorAll('video').forEach(forceInline);
    }, 2000);
})();