Youtube Player perf

Optimizes animation calls for lower GPU/CPU consumption

目前為 2023-07-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Youtube Player perf
// @version      0.4-beta
// @description  Optimizes animation calls for lower GPU/CPU consumption
// @namespace    nopeless.github.io
// @author       nopeless
// @match        https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

/* global _yt_player */

(() => {
    "use strict";

    const scaleX0 = Symbol("scaleX(0)");
    const scaleX1 = Symbol("scaleX(1)");

    function scaleX(el) {
        el.style.transform = "scaleX(0)";
        el[scaleX0] = true;
        el[scaleX1] = false;
    }

    function modifyBase() {
        console.log("Overriding _yt_player methods");

        if (!window._yt_player) return console.error("YT player not avaliable, load order is wrong");

        const PV = _yt_player.PV;

        // save the original prototype
        const PVPrototype = _yt_player.PV.prototype;

        let dirty = false;

        let chapterCount = 0;

        function update(a) {
            for (var b = _yt_player.u(Object.keys(a)), c = b.next(); !c.done; c = b.next()) {
                c = c.value;

                if (this.__updateCache.get(c) !== a[c]) {
                    // console.log("updating", c, a[c]);
                    this.updateValue(c, a[c]);
                    dirty = true;
                    this.__updateCache.set(c, a[c]);
                }
            }
        }

        // use ToolTip for checking
        let ytpToolTip = null;
        let ytpToolTipPreviousValue = null;

        _yt_player.PV = function (...args) {
            // YouTube base.js update approx 2023-07-28
            // this -> args[0]
            const a = args[0];

            PV.call(this, ...args);

            a.__updateCache = new Map();

            // override update
            a.update = update;

            // Side effects
            for (const selector of [
                "div.ytp-play-progress",
                "div.ytp-hover-progress",
                "div.ytp-load-progress",
            ]) {
                const xs = [...document.querySelectorAll(selector)];
                xs.forEach(scaleX);
                chapterCount = xs.length; // this is updated redundantly, idrc
            }

            ytpToolTip = document.querySelector("span.ytp-tooltip-text");
        };

        _yt_player.PV.prototype = Object.create(PVPrototype);
        _yt_player.PV.prototype.constructor = _yt_player.PV;

        const Un = _yt_player.Un;
        let counter = 0;

        let countChapters = -1;

        // YouTube base.js update approx 2023-07-28
        // Nn => Un
        _yt_player.Un = (a, b, c) => {
            // don't do excessive progress bar updates
            if (b === "transform") {
                let ih;

                if (dirty || ytpToolTip && (ih = ytpToolTip.innerHTML) !== ytpToolTipPreviousValue) {
                    counter = 2 + chapterCount * 2;
                    // console.log(counter);

                    dirty = false;
                    ytpToolTipPreviousValue = ih;
                }

                if (counter <= 0) return;

                counter--;

                // scalex(0) is almost useless after initial load
                if (c === "scalex(0)") {
                    if (a[scaleX0]) return;
                    a[scaleX0] = true;
                    a[scaleX1] = false;
                } else if (c === "scalex(1)") {
                    if (a[scaleX1]) return;
                    a[scaleX0] = false;
                    a[scaleX1] = true;
                } else {
                    a[scaleX0] = false;
                    a[scaleX1] = false;
                }

                // console.log(a, c);
            }
            Un(a, b, c);
        };
    }

    window.__modifyBase = modifyBase;

    const ob = new MutationObserver(mrs => {
        const l = mrs.map(mr => mr.addedNodes[0]).find(node => node && node.nodeName === "SCRIPT" && node.src && node.src.match(/\/base\.js$/));

        if (!l) return;

        l.setAttribute("onload", "__modifyBase()");

        ob.disconnect();
    });

    console.log("watching for script changes");
    ob.observe(document, { attributes: false, childList: true, subtree: true });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址