Greasy Fork is available in English.

Netflix UHD

Play Netflix UHD content on any screen resolution

Asenna tämä skripti?
Author's suggested script

Saatat myös pitää

Asenna tämä skripti
// ==UserScript==
// @name                 Netflix UHD
// @name:zh-CN           Netflix UHD
// @namespace            http://tampermonkey.net/
// @version              1.23
// @description          Play Netflix UHD content on any screen resolution
// @description:zh-CN    让 Netflix 在任何分辨率的显示器上播放 UHD 内容
// @author               TGSAN
// @match                https://www.netflix.com/*
// @icon                 https://www.google.com/s2/favicons?sz=64&domain=netflix.com
// @run-at               document-start
// @grant                unsafeWindow
// @grant                GM_registerMenuCommand
// ==/UserScript==

(function () {
    // 'use strict';

    const forceDolbyVision = false;
    const forceHEVC = false;
    const forceHDCP = false;

    let useWindowCtx

    if (self.unsafeWindow) {
        console.log("use unsafeWindow mode");
        useWindowCtx = self.unsafeWindow;
    } else {
        console.log("use window mode");
        useWindowCtx = self.window;
    }

    // Hook

    delete useWindowCtx.screen;
    useWindowCtx.__defineGetter__('screen', function () {
        let s = [];
        s.width = 7680;
        s.height = 4320;
        s.availWidth = 7680;
        s.availHeight = 4320;
        s.availLeft = 0;
        s.availTop = 0;
        s.colorDepth = 32;
        s.isExtended = false;
        s.pixelDepth = 32;
        return s;
    });
    delete useWindowCtx.devicePixelRatio;
    useWindowCtx.devicePixelRatio = 4;

    if (useWindowCtx.MSMediaKeys) {
        useWindowCtx.MSMediaKeys.isTypeSupportedWithFeaturesOriginal = useWindowCtx.MSMediaKeys.isTypeSupportedWithFeatures;
        useWindowCtx.MSMediaKeys.isTypeSupportedWithFeatures = function (a, b) {
            const reg = /,display-res-[x|y]=\d+,display-res-[x|y]=\d+/
            b = b.replace(reg, "");
            if (forceDolbyVision == true && (b.indexOf("ext-profile=dvh") !== -1)) {
                a = a.replace("com.microsoft.playready.hardware", "com.microsoft.playready");
            }
            if (forceHEVC == true && b.indexOf("ext-profile=dvh") === -1 && (b.indexOf("hvc1") !== -1 || b.indexOf("hev1") !== -1)) {
                a = a.replace("com.microsoft.playready.hardware", "com.microsoft.playready");
            }
            if (forceHDCP == true && b.indexOf("hdcp=") !== -1) {
                a = a.replace("hdcp=1", "");
                a = a.replace("hdcp=2", "");
            }
            let r = this.isTypeSupportedWithFeaturesOriginal(a, b);
            // if (r !== '') {
            //     console.log("Hook MSMediaKeys isTypeSupportedWithFeatures:", a, b, r !== '');
            // } else {
            //     console.debug("Hook MSMediaKeys isTypeSupportedWithFeatures:", a, b, r !== '');
            // }
            return r;
        }
    }

    if (useWindowCtx.WebKitMediaKeys) {
        useWindowCtx.WebKitMediaKeys.isTypeSupportedOriginal = useWindowCtx.WebKitMediaKeys.isTypeSupported;
        useWindowCtx.WebKitMediaKeys.isTypeSupported = function (keySystem, type) {
            let r = this.isTypeSupportedOriginal(keySystem, type);
            console.log("Hook WebKitMediaKeys", keySystem, type, r);
            return r;
        }
    }

    if (useWindowCtx.navigator.requestMediaKeySystemAccess) {
        useWindowCtx.navigator.requestMediaKeySystemAccessOriginal = useWindowCtx.navigator.requestMediaKeySystemAccess;
        useWindowCtx.navigator.requestMediaKeySystemAccess = async function (keySystem, options) {
            let newKeySystem = keySystem;
            if (keySystem.indexOf("playready") !== -1) {
                // newKeySystem = "com.microsoft.playready";
            }
            for (let oi = 0; options.length > oi; oi++) {
                if (options[oi].videoCapabilities != undefined) {
                    for (let vci = 0; options[oi].videoCapabilities.length > vci; vci++) {
                        if (options[oi].videoCapabilities[vci].robustness != undefined) {
                            // options[oi].videoCapabilities[vci].robustness = options[oi].videoCapabilities[vci].robustness.replace("HW_SECURE", "SW_SECURE");
                        }
                    }
                }
            }
            let r = await useWindowCtx.navigator.requestMediaKeySystemAccessOriginal(newKeySystem, options);
            // console.log(options);
            // console.log(r);
            return r;
        }
    }

    // WIP: Firefox not support
    // if (useWindowCtx.MediaSource) {
    //     useWindowCtx.MediaSource.isTypeSupportedOriginal = useWindowCtx.MediaSource.isTypeSupported;
    //     useWindowCtx.MediaSource.isTypeSupported = function (mimeType) {
    //         let r = this.isTypeSupportedOriginal(mimeType);
    //         console.log("Hook MSE", mimeType, r);
    //         return r;
    //     }
    // }

    if (useWindowCtx.MediaCapabilities.prototype) {
        useWindowCtx.MediaCapabilities.prototype.decodingInfoOriginal = useWindowCtx.MediaCapabilities.prototype.decodingInfo;
        useWindowCtx.MediaCapabilities.prototype.decodingInfo = function (mediaDecodingConfiguration) {
            let r = this.decodingInfoOriginal(mediaDecodingConfiguration);
            // console.log("MC", mediaDecodingConfiguration, r);
            let p = new Promise((res, rej) => {
                r.then(orir => {
                    // console.log("orir", orir);
                    orir.powerEfficient = orir.supported;
                    orir.smooth = orir.supported;
                    // console.log("orir edited", orir);
                    res(orir);
                }).catch(ex => {
                    rej(ex);
                });
            });
            return p;
        }
    }

    // Ext
    let checkHDCPAsync = async function () {
        if (self.GM_registerMenuCommand && window.MSMediaKeys) {
            // HW
            let hwhdcp0 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.hardware", 'video/mp4; features="hdcp=0"') != '';
            let hwhdcp1 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.hardware", 'video/mp4; features="hdcp=1"') != '';
            let hwhdcp2 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.hardware", 'video/mp4; features="hdcp=2"') != '';
            let hwhdcp2hevc = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.hardware", 'video/mp4; codecs="hev1,mp4a"; features="hdcp=2"') != '';
            let hwhdcp2hevc2160p = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.hardware", 'video/mp4; codecs="hev1,mp4a"; features="decode-res-x=3840,decode-res-y=2160,decode-bpc=10,hdcp=2"') != '';
            // SW
            let swhdcp0 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.software", 'video/mp4; features="hdcp=0"') != '';
            let swhdcp1 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.software", 'video/mp4; features="hdcp=1"') != '';
            let swhdcp2 = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.software", 'video/mp4; features="hdcp=2"') != '';
            let swhdcp2hevc = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.software", 'video/mp4; codecs="hev1,mp4a"; features="hdcp=2"') != '';
            let swhdcp2hevc2160p = window.MSMediaKeys.isTypeSupportedWithFeaturesOriginal("com.microsoft.playready.software", 'video/mp4; codecs="hev1,mp4a"; features="decode-res-x=3840,decode-res-y=2160,decode-bpc=10,hdcp=2"') != '';
            let bool2Status = function (booltype) {
                return booltype ? "✓" : "✕";
            };
            GM_registerMenuCommand("PlayReady DRM Info (" + (hwhdcp2hevc2160p ? "UHD Ready" : "Restricted") + ")", function () {
                // DHCP0
                let content = "PlayReady DRM (without HDCP 2.2):\n";
                content += "Hardware: " + bool2Status(hwhdcp0) + "    Software: " + bool2Status(swhdcp0) + "\n\n";
                // DHCP1
                content += "PlayReady DRM (HDCP 2.2):\n";
                content += "Hardware: " + bool2Status(hwhdcp1) + "    Software: " + bool2Status(swhdcp1) + "\n\n";
                // DHCP2
                content += "PlayReady DRM (HDCP 2.2 Type 1):\n";
                content += "Hardware: " + bool2Status(hwhdcp2) + "    Software: " + bool2Status(swhdcp2) + "\n\n";
                // DHCP2 + HEVC
                content += "PlayReady DRM (HDCP 2.2 Type 1) with HEVC:\n";
                content += "Hardware: " + bool2Status(hwhdcp2hevc) + "    Software: " + bool2Status(swhdcp2hevc) + "\n\n";
                // DHCP2 + HEVC 2160P
                content += "PlayReady DRM (HDCP 2.2 Type 1) with HEVC UHD:\n";
                content += "Hardware: " + bool2Status(hwhdcp2hevc2160p) + "    Software: " + bool2Status(swhdcp2hevc2160p) + "\n\n";
                // Display DRM Info
                alert(content);
            });
        }
    };
    checkHDCPAsync();

    let switchPlayerLog = function () {
        console.log("switch player log");

        useWindowCtx.dispatchEvent(new KeyboardEvent('keydown', {
            keyCode: 76,
            ctrlKey: true,
            altKey: true,
            shiftKey: true,
        }));
    }

    let loadLocalSubtitle = function () {
        console.log("load local subtitle");

        useWindowCtx.dispatchEvent(new KeyboardEvent('keydown', {
            keyCode: 84,
            ctrlKey: true,
            altKey: true,
            shiftKey: true,
        }));
    }

    let switchPlayerInfo = function () {
        console.log("switch player info");

        useWindowCtx.dispatchEvent(new KeyboardEvent('keydown', {
            keyCode: 68,
            ctrlKey: true,
            altKey: true,
            shiftKey: true,
        }));
    }

    let switchStreamSelector = function () {
        console.log("switch player info");

        useWindowCtx.dispatchEvent(new KeyboardEvent('keydown', {
            keyCode: 83, // S (Old)
            ctrlKey: true,
            altKey: true,
            shiftKey: true,
        }));

        useWindowCtx.dispatchEvent(new KeyboardEvent('keydown', {
            keyCode: 66, // B
            ctrlKey: true,
            altKey: true,
            shiftKey: true,
        }));
    }

    GM_registerMenuCommand("Player Info", switchPlayerInfo);
    GM_registerMenuCommand("Stream Selector", switchStreamSelector);
    GM_registerMenuCommand("Player Log", switchPlayerLog);
    GM_registerMenuCommand("Load Local Subtitle (.DFXP)", loadLocalSubtitle);
})();