您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
To make Quality Auto Max
当前为
- // ==UserScript==
- // @name YouTube: Quality Auto Max
- // @namespace UserScripts
- // @match https://www.youtube.com/*
- // @version 0.1.0
- // @author CY Fung
- // @license MIT
- // @description To make Quality Auto Max
- // @grant none
- // @run-at document-start
- // @unwrap
- // @inject-into page
- // ==/UserScript==
- (() => {
- const getL0 = (_yt_player) => {
- const w = 'L0';
- let arr = [];
- for (const [k, v] of Object.entries(_yt_player)) {
- const p = typeof v === 'function' ? v.prototype : 0;
- if (p) {
- let q = 0;
- if (typeof p.getPreferredQuality === 'function' && p.getPreferredQuality.length === 0) q += 200;
- if (typeof p.getVideoData === 'function' && p.getVideoData.length === 0) q += 80;
- if (typeof p.isPlaying === 'function' && p.isPlaying.length === 0) q += 2;
- if (typeof p.getPlayerState === 'function' && p.getPlayerState.length === 0) q += 2;
- if (typeof p.getPlayerType === 'function' && p.getPlayerType.length === 0) q += 2;
- if (q > 0) arr.push([k, q])
- }
- }
- if (arr.length === 0) {
- console.warn(`Key does not exist. [${w}]`);
- } else {
- if (arr.length > 1) arr.sort((a, b) => b[1] - a[1]);
- console.log(`[${w}]`, arr);
- return arr[0][0];
- }
- }
- const getZf = (vL0) => {
- const w = 'vL0';
- let arr = [];
- for (const [k, v] of Object.entries(vL0)) {
- // console.log(k,v)
- const p = v;
- if (p) {
- let q = 0;
- if (typeof p.videoData === 'object' && p.videoData) {
- if (Object.keys(p).length === 2) q += 200;
- }
- if (q > 0) arr.push([k, q])
- }
- }
- if (arr.length === 0) {
- // console.warn(`Key does not exist. [${w}]`);
- } else {
- if (arr.length > 1) arr.sort((a, b) => b[1] - a[1]);
- console.log(`[${w}]`, arr);
- return arr[0][0];
- }
- }
- const onRegistryReady = (callback) => {
- if (typeof customElements === 'undefined') {
- if (!('__CE_registry' in document)) {
- // https://github.com/webcomponents/polyfills/
- Object.defineProperty(document, '__CE_registry', {
- get() {
- // return undefined
- },
- set(nv) {
- if (typeof nv == 'object') {
- delete this.__CE_registry;
- this.__CE_registry = nv;
- this.dispatchEvent(new CustomEvent(EVENT_KEY_ON_REGISTRY_READY));
- }
- return true;
- },
- enumerable: false,
- configurable: true
- })
- }
- let eventHandler = (evt) => {
- document.removeEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
- const f = callback;
- callback = null;
- eventHandler = null;
- f();
- };
- document.addEventListener(EVENT_KEY_ON_REGISTRY_READY, eventHandler, false);
- } else {
- callback();
- }
- };
- const cleanContext = async (win) => {
- const waitFn = requestAnimationFrame; // shall have been binded to window
- try {
- let mx = 16; // MAX TRIAL
- const frameId = 'vanillajs-iframe-v1';
- /** @type {HTMLIFrameElement | null} */
- let frame = document.getElementById(frameId);
- let removeIframeFn = null;
- if (!frame) {
- frame = document.createElement('iframe');
- frame.id = frameId;
- const blobURL = typeof webkitCancelAnimationFrame === 'function' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
- frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
- let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
- n.appendChild(frame);
- while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
- const root = document.documentElement;
- root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
- if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
- removeIframeFn = (setTimeout) => {
- const removeIframeOnDocumentReady = (e) => {
- e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
- win = null;
- const m = n;
- n = null;
- setTimeout(() => m.remove(), 200);
- }
- if (document.readyState !== 'loading') {
- removeIframeOnDocumentReady();
- } else {
- win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
- }
- }
- }
- while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
- const fc = frame.contentWindow;
- if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
- const { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, requestIdleCallback, getComputedStyle } = fc;
- const res = { requestAnimationFrame, setTimeout, cancelAnimationFrame, setInterval, clearInterval, requestIdleCallback, getComputedStyle };
- for (let k in res) res[k] = res[k].bind(win); // necessary
- if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
- res.animate = fc.HTMLElement.prototype.animate;
- return res;
- } catch (e) {
- console.warn(e);
- return null;
- }
- };
- const promiseForCustomYtElementsReady = new Promise(onRegistryReady);
- cleanContext(window).then(__CONTEXT__ => {
- if (!__CONTEXT__) return null;
- const { setTimeout } = __CONTEXT__;
- const promiseForTamerTimeout = new Promise(resolve => {
- promiseForCustomYtElementsReady.then(() => {
- customElements.whenDefined('ytd-app').then(() => {
- setTimeout(resolve, 1200);
- });
- });
- setTimeout(resolve, 3000);
- });
- (async () => {
- const observablePromise = (proc, timeoutPromise) => {
- let promise = null;
- return {
- obtain() {
- if (!promise) {
- promise = new Promise(resolve => {
- let mo = null;
- const f = () => {
- let t = proc();
- if (t) {
- mo.disconnect();
- mo.takeRecords();
- mo = null;
- resolve(t);
- }
- }
- mo = new MutationObserver(f);
- mo.observe(document, { subtree: true, childList: true })
- f();
- timeoutPromise && timeoutPromise.then(() => {
- resolve(null)
- });
- });
- }
- return promise
- }
- }
- }
- const _yt_player = await observablePromise(() => {
- return (((window || 0)._yt_player || 0) || 0);
- }, promiseForTamerTimeout).obtain();
- if (!_yt_player || typeof _yt_player !== 'object') return;
- const vmHash = new WeakSet();
- const g = _yt_player;
- const keyL0 = getL0(_yt_player);
- if (keyL0) {
- let k = keyL0;
- let gk = g[k];
- let gkp = g[k].prototype;
- let keyZf = null;
- gkp.getVideoData31 = gkp.getVideoData;
- gkp.setupOnNewVideoData61 = function () {
- keyZf = getZf(this);
- if (!keyZf) return;
- const tZf = this[keyZf];
- if (!tZf) return;
- let keyJ = Object.keys(tZf).filter(e => e !== 'videoData')[0]
- const tZfJ = tZf[keyJ];
- const videoData = tZf.videoData;
- if (!tZfJ || !videoData || !tZfJ.videoInfos) return;
- let videoTypes = tZfJ.videoInfos.map(info => info.video);
- if (!videoTypes[0] || !videoTypes[0].quality || !videoTypes[0].height) return;
- let highestQuality = videoTypes[0].quality
- console.log('highestQuality', highestQuality)
- let keyLists = new Set();
- let keyLists2 = new Set();
- const o = {
- [keyZf]: {
- videoData: new Proxy(videoData, {
- get(obj, key) {
- keyLists.add(key);
- const v = obj[key];
- if (typeof v === 'object') return new Proxy(v, {
- get(obj, key) {
- keyLists2.add(key);
- return obj[key]
- }
- })
- return v
- }
- })
- }
- }
- this.getPreferredQuality.call(o)
- // console.log(keyLists.size, keyLists2.size)
- if (keyLists.size !== 2) return;
- if (keyLists2.size < 3) return;
- /*
- * 1080p Premium
- g.k.Nj = function(a) {
- h_a(this);
- this.options[a].element.setAttribute("aria-checked", "true");
- this.Yd(this.Dk(a));
- this.C = a
- }
- */
- /*
- TP = function(a) {
- return SP[a.j || a.B] || "auto"
- }
- */
- const [keyAy, keyxU] = [...keyLists];
- const keyLs = [...keyLists2]
- const keyPs = [keyAy, keyxU]
- let cz = 0;
- function inc() {
- for (const pey of keyPs) {
- for (const ley of keyLs) {
- const val = videoData[pey][ley]
- if (typeof val === 'number' && val >= 0 && ~~val === val) {
- if (!cz) cz = ley;
- if (cz === ley) {
- // videoData[pey][ley] = 5120;
- // videoData[pey][ley] = videoTypes[0].height;
- continue
- }
- videoData[pey][ley] = videoTypes[0].height;
- // videoData[pey][ley]='1080p Premium'
- // videoData[pey][ley] = '1080p';
- // videoData[pey]['reason']='m'
- } else if (typeof val === 'boolean' && val === false) {
- videoData[pey][ley] = true;
- }
- }
- }
- }
- inc();
- // console.log(22, this)
- // const keyyU=getyU(_yt_player);
- // _yt_player[keyyU].prototype.
- // (async()=>{
- // await customElements.whenDefined('ytd-watch-flexy');
- // await customElements.whenDefined('ytd-player');
- // await new Promise(r=>setTimeout(r, 800));
- // console.log(12321, document.querySelector('ytd-watch-flexy'))
- // console.log(12322, document.querySelector('ytd-watch-flexy').polymerController.player )
- // document.querySelector('ytd-watch-flexy').polymerController.player.setPlaybackQuality(highestQuality)
- // console.log(this.getPreferredQuality())
- // })();
- // inc();
- // console.log(this.getPreferredQuality())
- // inc();
- // console.log(this.getPreferredQuality())
- // console.log(videoData, keyxU)
- // console.log(this)
- // console.log(1237, keyZf, keyJ, this[keyZf], videoTypes, videoData[keyAy], videoData[keyxU], keyLists2)
- }
- gkp.getVideoData = function () {
- const vd = this.getVideoData31();;
- if (!vd || typeof vd !== 'object') return vd;
- if (!vmHash.has(vd)) {
- vmHash.add(vd);
- this.setupOnNewVideoData61();
- if (!keyZf) vmHash.delete(vd)
- }
- return vd;
- }
- }
- })();
- });
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址