iOS Video Force Inline Playback

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

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         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);
})();