您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
1/13/2024, 7:11:55 PM
当前为
// ==UserScript== // @name YouTube Live: Auto RealTime // @namespace UserScripts // @match https://www.youtube.com/* // @grant none // @version 0.2.7 // @author CY Fung // @description 1/13/2024, 7:11:55 PM // @run-at document-start // @require https://cdn.jsdelivr.net/gh/cyfung1031/userscript-supports@4871cab1b40a53521e6578f92ca10fc03b4ce823/library/nextBrowserTick.min.js // @license MIT // // ==/UserScript== (() => { let byPassPlaybackRate = false; let tmpPlaybackRate = null; if (typeof AbortSignal === 'undefined') return; const nextBrowserTick = (self || 0).nextBrowserTick || 0; let __requestAnimationFrame__ = typeof webkitRequestAnimationFrame === 'function' ? window.webkitRequestAnimationFrame.bind(window) : window.requestAnimationFrame.bind(window); if (!nextBrowserTick) return; let instance = null; /** @type {globalThis.PromiseConstructor} */ const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve. 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_; } } }; })(); 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 } } } let fc = 0; const pNextBrowserTick = () => new Promise(resolve => nextBrowserTick(resolve)); const pd = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate'); const isPassiveArgSupport = (typeof IntersectionObserver === 'function'); const bubblePassive = isPassiveArgSupport ? { capture: false, passive: true } : false; const capturePassive = isPassiveArgSupport ? { capture: true, passive: true } : true; const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0); let pageFetchedDataLocal = null; document.addEventListener('yt-page-data-fetched', (evt) => { pageFetchedDataLocal = evt.detail; }, bubblePassive); function getFormatDates() { if (!pageFetchedDataLocal) return null; const formatDates = {} try { formatDates.publishDate = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.publishDate } catch (e) { } // 2022-12-30 try { formatDates.uploadDate = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.uploadDate } catch (e) { } // 2022-12-30 try { formatDates.publishDate2 = pageFetchedDataLocal.pageData.response.contents.twoColumnWatchNextResults.results.results.contents[0].videoPrimaryInfoRenderer.dateText.simpleText } catch (e) { } // 2022/12/31 if (typeof formatDates.publishDate2 === 'string' && formatDates.publishDate2 !== formatDates.publishDate) { formatDates.publishDate = formatDates.publishDate2 formatDates.uploadDate = null } try { formatDates.broadcastBeginAt = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.startTimestamp } catch (e) { } try { formatDates.broadcastEndAt = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.endTimestamp } catch (e) { } try { formatDates.isLiveNow = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.isLiveNow } catch (e) { } return formatDates; } const promiseVideoNextFn = async (video, v) => { if (typeof video.requestVideoFrameCallback === 'function' && v !== false) { return true === await Promise.race([ new Promise(resolve => video.requestVideoFrameCallback(() => { resolve(true); })), new Promise(resolve => setTimeout(resolve, 1000)) ]); } else { return true === await Promise.race([ new Promise(resolve => video.addEventListener('timeupdate', () => { resolve(true); }, { once: true, passive: true, capture: false })), new Promise(resolve => setTimeout(resolve, 1000)) ]); } } let promisePR1; async function run(ut) { if (fc > 1e9) fc = 9; let tc = ++fc; const watchPages = [...document.querySelectorAll('ytd-watch-flexy')].filter(e => !e.closest('[hidden]')); if (watchPages.length !== 1 || !watchPages[0]) return; const watchPage = watchPages[0]; const timeout = new Promise(r => setTimeout(r, 1000)); const liveBtn = await observablePromise(() => watchPage.querySelector('button.ytp-live-badge.ytp-button[disabled]'), timeout).obtain(); if (tc !== fc) return; if (!liveBtn) return; if (liveBtn.closest('[hidden]')) return; if (!liveBtn.matches('.ytp-chrome-controls .ytp-live .ytp-live-badge')) return; await new Promise((resolve) => __requestAnimationFrame__(resolve)); if (tc !== fc) return; if (!liveBtn.isConnected) return; const settingBtn = watchPage.querySelector('button.ytp-button.ytp-settings-button:not([disabled])'); if (!settingBtn) return; if (settingBtn.closest('[hidden]')) return; const video = watchPage.querySelector('video.video-stream.html5-main-video'); if (!video) return; if (video.paused !== false) return; if (!pageFetchedDataLocal) return; const dates = getFormatDates(); // console.log(dates) await observablePromise(() => { if (video.paused || !video.isConnected || video.networkState !== 2 || video.readyState !== 4) return false; return video.currentTime > 0.1 && video.duration > 0.1 && instance; }, timeout).obtain(); if (tc !== fc) return; await new Promise(resolve => video.addEventListener('timeupdate', () => { resolve(); }, { once: true, passive: true, capture: false })); if (tc !== fc) return; // await new Promise((resolve) => __requestAnimationFrame__(resolve)); let setTime = null; if (dates.broadcastBeginAt && !dates.broadcastEndAt && dates.isLiveNow === true) { let t1 = video.currentTime; let t2 = (new Date() - new Date(dates.broadcastBeginAt)) / 1000; let te = video.duration; // console.log(12342, t1,t2) // console.log(12343, t1>0.8 , t2>0.8 , te>0.8 , t2-t1> 0.6 , te > t2 + 3.0 , te > t1 + 3.0) if (t1 > 0.8 && t2 > 0.8 && te > 0.8 && te > t2 + 3.0 && te > t1 + 3.0) { // await new Promise((resolve) => requestAnimationFrame(resolve)); // pd.set.call(video, 1.0); if (t2 - t1 > 0.6) { setTime = t2 - 0.49; } // console.log(4320, instance) // instance.setCurrentTime(t2, true); // setInterval(() => { // console.log(new Date(), video.currentTime, (new Date() - new Date(dates.broadcastBeginAt)) / 1000) // }, 1000); } } let crate = pd.get.call(video) if (!(crate > 0.99 && crate < 1.01)) return; // pd.set.call(video, 1); if (typeof setTime === 'number') { // video.currentTime = setTime; } // console.log('yyee') for (let i = 0; i < 2; i++) { promisePR1 = null; if (video.paused || !video.isConnected || video.networkState !== 2 || video.readyState !== 4) return; if (false === await promiseVideoNextFn(video)) return; if (tc !== fc) return; byPassPlaybackRate = true; const pr = promisePR1 = new PromiseExternal(); instance.setPlaybackRate((i === 0 ? 13.52 + Math.random() * 0.45 : 1.26 + Math.random() * 0.22), true); if (video.paused || !video.isConnected || video.networkState !== 2 || video.readyState !== 4) { } else { await promiseVideoNextFn(video); } await pr.then(); await promiseVideoNextFn(video); await promiseVideoNextFn(video, false); byPassPlaybackRate = false; } /* console.log(12312) console.log() if (tc !== fc) return; settingBtn.click(); await pNextBrowserTick(); let menuItemBtns = [...watchPage.querySelectorAll('.ytp-panel .ytp-menuitem[aria-haspopup]')].filter(e => { return e.querySelector('[d^="M10,8v8l6-4L10,"]') }); if (menuItemBtns.length !== 1 || !menuItemBtns[0]) return; let menuItemBtn = menuItemBtns[0] menuItemBtn.click(); await pNextBrowserTick(); let radioBtns = [...watchPage.querySelectorAll('.ytp-popup.ytp-settings-menu .ytp-panel-menu .ytp-menuitem[role="menuitemradio"]')].filter(e => { return e.textContent.trim() === '2' }); if (radioBtns.length !== 1 || !radioBtns[0]) return; let radioBtn = radioBtns[0]; radioBtn.click(); await pNextBrowserTick(); pd.set.call(video, 8.98); if (radioBtn.isConnected) settingBtn.click(); */ // console.log(1232131) } document.addEventListener('yt-navigate-finish', () => { run(0); }, false); const _yt_player_observable = observablePromise(() => { return (((window || 0)._yt_player || 0) || 0); }); (async () => { const _yt_player = await _yt_player_observable.obtain(); if (!_yt_player || typeof _yt_player !== 'object') return; 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 getGU = (_yt_player) => { const w = 'GU'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.setPlaybackRate === 'function' && p.setPlaybackRate.length === 2 && typeof p.getPlaybackRate === 'function' && p.getPlaybackRate.length === 0 // && typeof p.isAtLiveHead === 'function' && typeof p.getVideoUrl === 'function' && p.getVideoUrl.length === 4 && typeof p.getCurrentTime === 'function' && p.getCurrentTime.length == 2 && typeof p.getDuration === 'function' && p.getDuration.length == 2 && !(typeof p.isPaused === 'function' && p.isPaused.length === 0 && typeof p.getCurrentTime === 'function' && p.getCurrentTime.length === 0 && typeof p.getDuration === 'function' && p.getDuration.length === 0 // && typeof p.isAtLiveHead === 'function' && p.isAtLiveHead.length === 0 && typeof p.getVideoPlaybackQuality === 'function' && p.getVideoPlaybackQuality.length === 0 && typeof p.stopVideo === 'function' && p.stopVideo.length === 0) // && Object.keys(_yt_player[k].prototype).includes('addEventListener') // && !p.dispose && !p.isDisposed ) { arr = addProtoToArr(_yt_player, k, arr) || arr; } } // console.log(1222, arr.map(k=> Object.keys(_yt_player[k].prototype).sort())) if (arr.length === 0) { console.warn(`Key does not exist. [${w}]`); } else { console.log(`[${w}]`, arr); return arr[0]; } } const getW0 = (_yt_player) => { const w = 'W0'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.isAtLiveHead === 'function' && typeof p.seekTo === 'function' && typeof p.loadVideoByPlayerVars === 'undefined' ) { arr = addProtoToArr(_yt_player, k, arr) || arr; } } // console.log(1222, arr.map(k=> _yt_player[k].prototype['isAtLiveHead'])) // console.log(1223, arr.map(k=> Object.keys( _yt_player[k].prototype))) if (arr.length === 0) { console.warn(`Key does not exist. [${w}]`); } else { console.log(`[${w}]`, arr); return arr[0]; } } const getg1 = (_yt_player) => { const w = 'g1'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.canPlayType === 'function' && p.canPlayType.length === 1 && typeof p.cancelPlayback === 'function' && p.cancelPlayback.length === 2 && typeof p.getInternalApi === 'function' && p.getInternalApi.length === 0 && typeof p.getAppState === 'function' && p.getAppState.length === 0 && typeof p.getPresentingPlayerType === 'function' && p.getPresentingPlayerType.length === 1 && typeof p.getVideoData === 'function' && p.getVideoData.length === 0 && typeof p.seekTo === 'function' && typeof p.seekBy === 'function' && typeof p.sendVideoStatsEngageEvent === 'function' ) { arr = addProtoToArr(_yt_player, k, arr) || arr; } } // console.log(1222, arr.map(k=> _yt_player[k].prototype['isAtLiveHead'])) // console.log(1223, arr.map(k=> Object.keys( _yt_player[k].prototype))) if (arr.length === 0) { console.warn(`Key does not exist. [${w}]`); } else { console.log(`[${w}]`, arr); return arr[0]; } } const key = getGU(_yt_player); // console.log(1233, key) const g = _yt_player; const k = key; const gk = g[k]; const gkp = g[k].prototype; // gkp.isAtLiveHead322 = gkp.isAtLiveHead; // gkp.isAtLiveHead = function(){ // // console.log(5555) // instance = this; // return this.isAtLiveHead322(); // } gkp.getPlaybackRate322 = gkp.getPlaybackRate; gkp.getPlaybackRate = function () { // console.log(5556, this.getPlaybackRate322) instance = this; return this.getPlaybackRate322(); } gkp.setPlaybackRate322 = gkp.setPlaybackRate; gkp.setPlaybackRate = function (a, b) { instance = this; if (byPassPlaybackRate) { // console.log(5888, 12333,a, b) // return; } // console.log(5388, arguments) return this.setPlaybackRate322(a, b); } let key2 = getW0(_yt_player); // console.log('XXA', key2) let key3 = getg1(_yt_player); // console.log('XXB', key3) /* _yt_player[key3].prototype.E8xx = _yt_player[key3].prototype.E8; _yt_player[key3].prototype.E8 = function(a){ let b1= g.sH(a, 1); let b2= !g.qH(a.state, 64) let b3= this.Hd().isLivePlayback; let b4= this.zb.isAtLiveHead(); let b5= 1 < this.Va.getPlaybackRate(); console.log('XXPP0', a) console.log('XXPP1' , b1,b2,b3,b4,b5) setTimeout(()=>{ let b1= g.sH(a, 1); let b2= !g.qH(a.state, 64) let b3= this.Hd().isLivePlayback; let b4= this.zb.isAtLiveHead(); let b5= 1 < this.Va.getPlaybackRate(); // console.log('XXPP2' , b1,b2,b3,b4,b5) }, 1000) return this.E8xx(a); } */ })(); Storage.prototype.setItem322 = Storage.prototype.setItem; Storage.prototype.setItem = function (a, b) { if (a === 'yt-player-playback-rate') { tmpPlaybackRate = b; // if(!byPassPlaybackRate) debugger if (promisePR1 && b && typeof b === 'string' && b.indexOf('{"data":"1"') >= 0) { promisePR1.resolve(); promisePR1 = null; } // console.log(5883, a, b,byPassPlaybackRate, 'XX_'+tmpPlaybackRate+'_', location.pathname) if (window.location.pathname === '/live_chat') return; } if (byPassPlaybackRate && a === 'yt-player-playback-rate') return; this.setItem322(a, b); } Storage.prototype.getItem322 = Storage.prototype.getItem; Storage.prototype.getItem = function (a) { if (a === 'yt-player-playback-rate') { if (window.location.pathname === '/live_chat') return null; // console.log(5884, a, 'XX_'+tmpPlaybackRate+'_', location.pathname) if (typeof tmpPlaybackRate === 'string') return tmpPlaybackRate; } if (a === 'yt-player-playback-rate' && typeof tmpPlaybackRate === 'string') return tmpPlaybackRate; return this.getItem322(a); } Object.defineProperty(Storage.prototype, 'yt-player-playback-rate', { get() { // console.log(5881, 'XX_'+tmpPlaybackRate+'_', location.pathname) return this.getItem('yt-player-playback-rate'); }, set(nv) { // console.log(5882, nv, 'XX_'+tmpPlaybackRate+'_', location.pathname); this.setItem('yt-player-playback-rate', nv); return true; }, enumerable: true, configurable: true }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址