您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
To make AutoPlay Next Duration longer
当前为
// ==UserScript== // @name YouTube: Make AutoPlay Next More Than 3 seconds // @namespace UserScripts // @match https://www.youtube.com/* // @version 0.2.3 // @author CY Fung // @license MIT // @description To make AutoPlay Next Duration longer // @grant none // @run-at document-start // @unwrap // @inject-into page // ==/UserScript== (() => { const second_to_play_next = +localStorage.second_to_play_next || 8; const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0); const Promise = (async () => { })().constructor; /* * , $mb = function(a, b) { b = void 0 === b ? -1 : b; a = a.j.Ha("ytp-autonav-endscreen-upnext-header"); g.of(a); if (0 <= b) { b = String(b); var c = "$SECONDS \u79d2\u5f8c\u306b\u6b21\u306e\u52d5\u753b\u3092\u518d\u751f".match(RegExp("\\$SECONDS", "gi"))[0] , d = "$SECONDS \u79d2\u5f8c\u306b\u6b21\u306e\u52d5\u753b\u3092\u518d\u751f".indexOf(c); if (0 <= d) { a.appendChild(g.mf("$SECONDS \u79d2\u5f8c\u306b\u6b21\u306e\u52d5\u753b\u3092\u518d\u751f".slice(0, d))); var e = g.lf("span"); g.$t(e, "ytp-autonav-endscreen-upnext-header-countdown-number"); g.Bf(e, b); a.appendChild(e); a.appendChild(g.mf("$SECONDS \u79d2\u5f8c\u306b\u6b21\u306e\u52d5\u753b\u3092\u518d\u751f".slice(d + c.length))); return } } g.Bf(a, "\u6b21\u306e\u52d5\u753b") } */ /* * if (!a.Qk()) { a.J.Bf() ? $mb(a, Math.round(anb(a) / 1E3)) : $mb(a); b = !!a.suggestion && !!a.suggestion.Bs; var c = a.J.Bf() || !b; g.fu(a.container.element, "ytp-autonav-endscreen-upnext-alternative-header-only", !c && b); g.fu(a.container.element, "ytp-autonav-endscreen-upnext-no-alternative-header", c && !b); g.FG(a.B, a.J.Bf()); g.fu(a.element, "ytp-enable-w2w-color-transitions", bnb(a)) } */ /* * * , anb = function(a) { if (a.J.isFullscreen()) { var b; a = null == (b = a.J.getVideoData()) ? void 0 : b.CB; return -1 === a || void 0 === a ? 8E3 : a } return 0 <= a.J.Ss() ? a.J.Ss() : g.WJ(a.J.W().experiments, "autoplay_time") || 1E4 } */ // a.J instanceof g.AU /* * * g.AU {Dp: false, xk: undefined, app: g.b1, state: WQa, playerType: undefined, …} Dp: false UK: pYa {Dp: false, xk: Array(6), Ub: {…}, Td: {…}, element: div#ytp-id-18.ytp-popup.ytp-settings-menu, …} app: g.b1 {Dp: false, xk: Array(21), logger: g.pY, di: false, bA: false, …} element: null j: false playerType: undefined state: WQa {Dp: false, xk: undefined, D: Set(89), G: {…}, S: {…}, …} xk: undefined */ // a.J.Ss = ƒ (){return this.app.Ss()} // a.J.app.Ss = ƒ (){return this.getVideoData().aU} // a.J.app.getVideoData() = ƒ (){return this.Qb.getVideoData()} = object instanceof g.sT // a.J.app.Qb.getVideoData = ƒ (){return this.videoData} // g.sT.prototype /* * getAudioTrack getAvailableAudioTracks getHeartbeatResponse getPlayerResponse getPlaylistSequenceForTime getStoryboardFormat hasProgressBarBoundaries hasSupportedAudio51Tracks isAd isDaiEnabled isLoaded isOtf useInnertubeDrmService */ const getsT = (_yt_player) => { const w = 'sT'; 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.hasSupportedAudio51Tracks === 'function' && p.hasSupportedAudio51Tracks.length === 0) q += 2; if (typeof p.getStoryboardFormat === 'function' && p.getStoryboardFormat.length === 0) q += 4; if (typeof p.getPlaylistSequenceForTime === 'function' && p.getPlaylistSequenceForTime.length === 1) q += 4; if (typeof p.isLoaded === 'function' && p.isLoaded.length === 0) q += 200; if (typeof p.isOtf === 'function' && p.isOtf.length === 0) q += 2; if (typeof p.getAvailableAudioTracks === 'function' && p.getAvailableAudioTracks.length === 0) q += 4; if (typeof p.getAudioTrack === 'function' && p.getAudioTrack.length === 0) q += 4; if (typeof p.getPlayerResponse === 'function' && p.getPlayerResponse.length === 0) q += 2; if (typeof p.getHeartbeatResponse === 'function' && p.getHeartbeatResponse.length === 0) q += 2; if (typeof p.isAd === 'function' && p.isAd.length === 0) q += 2; if (typeof p.isDaiEnabled === 'function' && p.isDaiEnabled.length === 1) q += 2; if (typeof p.useInnertubeDrmService === 'function' && p.useInnertubeDrmService.length === 0) q++; if (typeof p.hasProgressBarBoundaries === 'function' && p.hasProgressBarBoundaries.length === 0) q += 2; if (q < 200) continue; // p.isLoaded is required 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 addProtoToArr = (parent, key, arr) => { let isChildProto = false; for (const sr of arr) { if (parent[key].prototype instanceof parent[sr]) { isChildProto = true; break; } } if (isChildProto) return; arr = arr.filter(sr => { if (parent[sr].prototype instanceof parent[key]) { return false; } return true; }); arr.push(key); return arr; } const getAU = (_yt_player) => { const w = 'VG'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.show === 'function' && p.show.length === 1 && typeof p.hide === 'function' && p.hide.length === 0 && typeof p.stop === 'function' && p.stop.length === 0) { arr = addProtoToArr(_yt_player, k, arr) || arr; } } if (arr.length === 0) { console.warn(`Key does not exist. [${w}]`); } else { console.log(`[${w}]`, arr); return arr[0]; } } 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; } }; cleanContext(window).then(__CONTEXT__ => { if (!__CONTEXT__) return null; const { setTimeout } = __CONTEXT__; const isUrlInEmbed = location.href.includes('.youtube.com/embed/'); const isAbortSignalSupported = typeof AbortSignal !== "undefined"; const promiseForTamerTimeout = new Promise(resolve => { !isUrlInEmbed && isAbortSignalSupported && document.addEventListener('yt-action', function () { setTimeout(resolve, 480); }, { capture: true, passive: true, once: true }); !isUrlInEmbed && isAbortSignalSupported && typeof customElements === "object" && customElements.whenDefined('ytd-app').then(() => { setTimeout(resolve, 1200); }); setTimeout(resolve, 3000); }); const PromiseExternal = ((resolve_, reject_) => { const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject }; return class PromiseExternal extends Promise { constructor(cb = h) { super(cb); if (cb === h) { /** @type {(value: any) => void} */ this.resolve = resolve_; /** @type {(reason?: any) => void} */ this.reject = reject_; } } }; })(); (async () => { const dataSetPromise = new PromiseExternal(); const instSetPromise = new PromiseExternal(); 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 } } } if (isAbortSignalSupported && !isUrlInEmbed) { await customElements.whenDefined('ytd-player'); } const _yt_player = await observablePromise(() => { return (((window || 0)._yt_player || 0) || 0); }, promiseForTamerTimeout).obtain(); if (!_yt_player || typeof _yt_player !== 'object') return; function baseSet() { let r = setDataHolder(); if (r) qrz ? assignDurationToData(pm.playerOverlayAutoplayRenderer, null) : dataSetPromise.resolve(); // if (pm.targetKeys && pm.instsT) { // qtd = true; // } } function onSetsT(inst) { if (!inst) return; baseSet(); instSetPromise.resolve(); } const pm = new Proxy({}, { set(target, prop, value, receiver) { let old = target[prop]; if (old !== value) { target[prop] = old = value; if (prop === 'instsT') onSetsT(value); } } }); const assignDurationToData = (playerOverlayAutoplayRenderer) => { if (!playerOverlayAutoplayRenderer) return; const t4 = playerOverlayAutoplayRenderer.countDownSecsForFullscreen; const t5 = playerOverlayAutoplayRenderer.countDownSecs; let b = t4 === t5 playerOverlayAutoplayRenderer.countDownSecsForFullscreen = second_to_play_next; if (b) playerOverlayAutoplayRenderer.countDownSecs = second_to_play_next; return b; } let qrz = false; // let qtd = false; Promise.all([dataSetPromise, instSetPromise]).then(() => { const inst = pm.instsT; const playerOverlayAutoplayRenderer = pm.playerOverlayAutoplayRenderer; if (!inst || !playerOverlayAutoplayRenderer) return; let entriesA = Object.entries(inst).filter(e => typeof e[1] === 'number'); let m = new Map(); for (const entry of entriesA) { m.set(entry[0], entry[1]); } let b = assignDurationToData(playerOverlayAutoplayRenderer); setTimeout(() => { const entriesB = Object.entries(inst).filter(e => typeof e[1] === 'number' && m.get(e[0]) !== e[1]); m = null; let filtered = entriesB.filter(e => Math.abs(e[1] - second_to_play_next * 1E3) < 1e-8); if (filtered.length >= 1) { pm.targetKeys = filtered.map(e => e[0]); } else { pm.targetKeys = null; } console.log(`sT(${b ? 'T' : 'F'}):`, filtered, filtered.length) }, 80); qrz = true; }); const setDataHolder = () => { let playerOverlayAutoplayRenderer = null; let pageDataMgr = document.querySelector('ytd-page-manager#page-manager'); let pageData = pageDataMgr ? insp(pageDataMgr).data : null; if (pageData) { try { playerOverlayAutoplayRenderer = pageData.response.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer; } catch (e) { } } if (playerOverlayAutoplayRenderer && typeof playerOverlayAutoplayRenderer.countDownSecsForFullscreen === 'number' && playerOverlayAutoplayRenderer.countDownSecsForFullscreen < 15) { pm.playerOverlayAutoplayRenderer = playerOverlayAutoplayRenderer; return true; } }; document.addEventListener('yt-navigate-finish', function () { // onSetsT(pm.instsT) baseSet(); }, false); const g = _yt_player; const keysT = getsT(_yt_player); if (keysT) { let k = keysT; let gk = g[k]; let gkp = g[k].prototype; /* * if (typeof p.hasSupportedAudio51Tracks === 'function' && p.hasSupportedAudio51Tracks.length === 0) q += 2; if (typeof p.getStoryboardFormat === 'function' && p.getStoryboardFormat.length === 0) q += 4; if (typeof p.getPlaylistSequenceForTime === 'function' && p.getPlaylistSequenceForTime.length === 1) q += 4; if (typeof p.isLoaded === 'function' && p.isLoaded.length === 0) q += 2; if (typeof p.isOtf === 'function' && p.isOtf.length === 0) q += 2; if (typeof p.getAvailableAudioTracks === 'function' && p.getAvailableAudioTracks.length === 0) q += 4; if (typeof p.getAudioTrack === 'function' && p.getAudioTrack.length === 0) q += 4; if (typeof p.getPlayerResponse === 'function' && p.getPlayerResponse.length === 0) q += 2; if (typeof p.getHeartbeatResponse === 'function' && p.getHeartbeatResponse.length === 0) q += 2; if (typeof p.isAd === 'function' && p.isAd.length === 0) q += 2; if (typeof p.isDaiEnabled === 'function' && p.isDaiEnabled.length === 1) q += 2; if (typeof p.useInnertubeDrmService === 'function' && p.useInnertubeDrmService.length === 0) q++; if (typeof p.hasProgressBarBoundaries === 'function' && p.hasProgressBarBoundaries.length === 0) q += 2; */ // for(const pk of ['hasSupportedAudio51Tracks','getStoryboardFormat','getPlaylistSequenceForTime','isLoaded', // 'isOtf',//'getAvailableAudioTracks','getAudioTrack', // 'getPlayerResponse','getHeartbeatResponse', // // 'isAd', // 'isDaiEnabled','useInnertubeDrmService', // //'hasProgressBarBoundaries' // ]){ // if(gkp[pk]){ // gkp[pk+'75'] = gkp[pk]; // gkp[pk]=function(){ // console.log(pk) // return this[pk+'75'].apply(this, arguments); // } // } // } if (!gkp.isLoaded75 && typeof gkp.isLoaded === 'function') { gkp.isLoaded75 = gkp.isLoaded; gkp.isLoaded = function () { pm.instsT = this; // if (qtd) { // qtd = false; // setTimeout(() => { // const inst = pm.instsT; // if (pm.targetKeys && inst) { // const entries = pm.targetKeys.map(k => [k, inst[k]]); // console.log(`sT:`, entries, entries.length); // } // }, 80); // } return this.isLoaded75.apply(this, arguments); } } } // console.log(keysT); // const sT = [_yt_player] })(); }); })();