// ==UserScript== // @name YouTube: Audio Only // @description No Video Streaming // @namespace UserScript // @version 1.9.4 // @author CY Fung // @match https://www.youtube.com/* // @match https://www.youtube.com/embed/* // @match https://www.youtube-nocookie.com/embed/* // @match https://m.youtube.com/* // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/ // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/YouTube-Audio-Only.png // @grant GM_registerMenuCommand // @grant GM.setValue // @grant GM.getValue // @grant GM.listValues // @grant GM.deleteValue // @run-at document-start // @license MIT // @compatible chrome // @compatible firefox // @compatible opera // @compatible edge // @compatible safari // @allFrames true // // @downloadURL none // ==/UserScript== (async function () { 'use strict'; !window.TTP && (() => { // credit to Benjamin Philipp // original source: https://greasyfork.org/en/scripts/433051-trusted-types-helper // --------------------------------------------------- Trusted Types Helper --------------------------------------------------- const overwrite_default = false; // If a default policy already exists, it might be best not to overwrite it, but to try and set a custom policy and use it to manually generate trusted types. Try at your own risk const prefix = `TTP`; var passThroughFunc = function (string, sink) { return string; // Anything passing through this function will be returned without change } var TTPName = "passthrough"; var TTP_default, TTP = { createHTML: passThroughFunc, createScript: passThroughFunc, createScriptURL: passThroughFunc }; // We can use TTP.createHTML for all our assignments even if we don't need or even have Trusted Types; this should make fallbacks and polyfills easy var needsTrustedHTML = false; function doit() { try { if (typeof window.isSecureContext !== 'undefined' && window.isSecureContext) { if (window.trustedTypes && window.trustedTypes.createPolicy) { needsTrustedHTML = true; if (trustedTypes.defaultPolicy) { log("TT Default Policy exists"); if (overwrite_default) TTP = window.trustedTypes.createPolicy("default", TTP); else TTP = window.trustedTypes.createPolicy(TTPName, TTP); // Is the default policy permissive enough? If it already exists, best not to overwrite it TTP_default = trustedTypes.defaultPolicy; log("Created custom passthrough policy, in case the default policy is too restrictive: Use Policy '" + TTPName + "' in var 'TTP':", TTP); } else { TTP_default = TTP = window.trustedTypes.createPolicy("default", TTP); } log("Trusted-Type Policies: TTP:", TTP, "TTP_default:", TTP_default); } } } catch (e) { log(e); } } function log(...args) { if ("undefined" != typeof (prefix) && !!prefix) args = [prefix + ":", ...args]; if ("undefined" != typeof (debugging) && !!debugging) args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")]; console.log(...args); } doit(); // --------------------------------------------------- Trusted Types Helper --------------------------------------------------- window.TTP = TTP; })(); function createHTML(s) { if (typeof TTP !== 'undefined' && typeof TTP.createHTML === 'function') return TTP.createHTML(s); return s; } let trustHTMLErr = null; try { document.createElement('div').innerHTML = createHTML('1'); } catch (e) { trustHTMLErr = e; } if (trustHTMLErr) { console.log(`trustHTMLErr`, trustHTMLErr); trustHTMLErr(); // exit userscript } /** @type {globalThis.PromiseConstructor} */ const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve. if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError"); async function confirm(message) { // Create the HTML for the dialog if (!document.body) return; let dialog = document.getElementById('confirmDialog794'); if (!dialog) { const dialogHTML = `

${message}

`; // Append the dialog to the document body document.body.insertAdjacentHTML('beforeend', createHTML(dialogHTML)); dialog = document.getElementById('confirmDialog794'); } // Return a promise that resolves or rejects based on the user's choice return new Promise((resolve) => { document.getElementById('confirmBtn').onclick = () => { resolve(true); cleanup(); }; document.getElementById('cancelBtn').onclick = () => { resolve(false); cleanup(); }; function cleanup() { dialog && dialog.remove(); dialog = null; } }); } if (location.pathname === '/live_chat' || location.pathname === 'live_chat_replay') return; const kEventListener = (evt) => { if (document.documentElement.hasAttribute('forceRefresh032')) { evt.stopImmediatePropagation(); evt.stopPropagation(); } } window.addEventListener('beforeunload', kEventListener, false); const pageInjectionCode = function () { let debugFlg001 = false; // let debugFlg002 = false; let globalPlayer = null; const SHOW_VIDEO_STATIC_IMAGE = true; const PATCH_MEDIA_PUBLISH = true; if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError"); const URL = window.URL || new Function('return URL')(); const createObjectURL = URL.createObjectURL.bind(URL); /** @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_; } } }; })(); /* globals WeakRef:false */ /** @type {(o: Object | null) => WeakRef | null} */ const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null); /** @type {(wr: Object | null) => Object | null} */ const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr); /* g.k.playVideo = function(a) { this.logger.debug(function() { return "play video, player type " + a }); var b = g.rT(this, a); b && (this.appState === 2 ? (g.BR(this.X) && $U(this.Rb), N0(this)) : g.pF(b.getPlayerState(), 2) ? (b = 36, this.getVideoData().nk() && (b = 37), this.seekTo(0, void 0, void 0, void 0, b)) : b.playVideo()) } g.k.getPresentingPlayerType = function(a) { if (this.appState === 1) return 1; if (J0(this)) return 3; var b; if (a && ((b = this.ye) == null ? 0 : b.vl(this.getCurrentTime()))) return 2; var c; return g.zS(this.getVideoData()) && ((c = this.wb) == null ? 0 : c.vl()) ? 2 : g.rT(this).getPlayerType() } g.k.rS = function() { var a = this.app.getPresentingPlayerType(); if (a === 2 && !this.app.Jf()) { var b = zV(this.app.zb()); if (!Dkb(b) || Ekb(b)) return } a === 3 ? AT(this.app.zb()).iG("control_play") : this.app.U().L("html5_ssap_ignore_play_for_ad") && g.zS(this.app.Od()) && a === 2 || this.app.playVideo(a) } */ // const onDurationAvailable = async function(player_, media){ // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 1) { // skipPause = true; // skipVisibility = true; // debugFlg002 && console.log(1991, player_.getPresentingPlayerType()) // await player_.cancelPlayback(); // debugFlg002 && console.log(1992, player_.getPresentingPlayerType()) // await player_.pauseVideo(); // debugFlg002 && console.log(1993, player_.getPresentingPlayerType()) // // window.m33e = 1; // window.m34e = player_; // // await player_.clearQueue(); // await player_.playVideo(); // skipVisibility = false; // skipPause = false; // debugFlg002 && console.log('HTMLMediaElement A2', [media.readyState, media.paused, media.networkState]); // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 4) { // media.__canPlayPromise__.resolve(); // media.__canPlayPromise__ = null; // } // } // } // let skipPause = false; // let skipVisibility = false; // const durationchangeListener = async function (evt) { // const media = evt ? evt.target : null; // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 1) { // if (media.readyState < 4) { // debugFlg002 && console.log('HTMLMediaElement A1', [media.readyState, media.paused, media.networkState]) // const player_ = kRef(globalPlayer); // if (player_) { // onDurationAvailable(player_, media); // } else { // console.error("HTMLMediaElement", "player_ is not found when HTMLMediaElement duration change"); // } // } else { // debugFlg002 && console.log('HTMLMediaElement B', [media.readyState, media.paused, media.networkState]) // media.__canPlayPromise__.resolve(); // media.__canPlayPromise__ = null; // } // } // } // const canplayListener = function (evt) { // const media = evt ? evt.target : null; // if (media && media.__canPlayPromise__) { // debugFlg002 && console.log('HTMLMediaElement canplay', [media.readyState, media.paused, media.networkState]); // media.__canPlayPromise__.resolve(); // media.__canPlayPromise__ = null; // } // debugFlg002 && console.log('HTMLMediaElement canplay') // } // let x6CGdPr = null; // window.addEventListener('message', (evt)=>{ // if((evt||0).data === 'x6CGd' && x6CGdPr!==null) x6CGdPr.resolve(); // }); // const timelineResolve = async () => { // if (x6CGdPr !== null) { // await x6CGdPr.then(); // return; // } // x6CGdPr = new PromiseExternal(); // window.postMessage('x6CGd'); // await x6CGdPr.then(); // x6CGdPr = null; // } // let playWId = 0; // const mediaPlay = HTMLMediaElement.prototype.play // HTMLMediaElement.prototype.play = function () { // debugFlg002 && console.log('HTMLMediaElement play') // if (playWId > 1e9) playWId = 9; // const tid = ++playWId; // if (!this.paused) { // return mediaPlay.apply(this, arguments); // } // if (this.readyState >= 4) return mediaPlay.apply(this, arguments); // try { // if (!this.__canPlayPromise__ && this.closest('#player')) { // this.__canPlayPromise__ = new PromiseExternal(); // const player_ = kRef(globalPlayer); // debugFlg002 && console.log('HTMLMediaElement play x', this.duration, player_) // if (!(this.duration > 0)) { // this.removeEventListener('durationchange', durationchangeListener); // this.addEventListener('durationchange', durationchangeListener); // this.removeEventListener('canplay', canplayListener); // this.addEventListener('canplay', canplayListener); // } else if (player_) { // this.removeEventListener('canplay', canplayListener); // this.addEventListener('canplay', canplayListener); // onDurationAvailable(player_, this); // } else { // console.error("HTMLMediaElement", "player_ is not found when HTMLMediaElement plays"); // } // //--------------- // // this.addEventListener('canplaythrough', function(){ // // console.log('HTMLMediaElement canplaythrough') // // }); // // this.addEventListener('loadeddata', function(){ // // console.log('HTMLMediaElement loadeddata') // // }); // // this.addEventListener('loadedmetadata', function(){ // // console.log('HTMLMediaElement loadedmetadata') // // }); // //--------------- // // this.addEventListener('abort', function(){ // // console.log('HTMLMediaElement abort') // // }); // // this.addEventListener('emptied', function(){ // // console.log('HTMLMediaElement emptied') // // }); // // this.addEventListener('error', function(){ // // console.log('HTMLMediaElement error') // // }); // // this.addEventListener('ended', function(){ // // console.log('HTMLMediaElement ended') // // }); // // this.addEventListener('loadstart', function(){ // // console.log('HTMLMediaElement loadstart') // // }); // } // } catch (e) { // console.log('HTMLMediaElement.prototype.play error'); // console.error(e); // this.__canPlayPromise__ = Promise.resolve(); // } // const promise = this.__canPlayPromise__; // return (async () => { // await promise.then(); // if (tid !== playWId) return; // return await mediaPlay.apply(this, arguments); // })(); // } // const mediaPause = HTMLMediaElement.prototype.pause // HTMLMediaElement.prototype.pause = function () { // if (skipPause) return; // debugFlg002 && console.log('HTMLMediaElement pause') // if (playWId > 1e9) playWId = 9; // const tid = ++playWId; // const promise = this.__canPlayPromise__; // if (promise) { // promise.resolve(); // this.__canPlayPromise__ = null; // } // return mediaPause.apply(this, arguments); // } const createPipeline = () => { let pipelineMutex = Promise.resolve(); const pipelineExecution = fn => { return new Promise((resolve, reject) => { pipelineMutex = pipelineMutex.then(async () => { let res; try { res = await fn(); } catch (e) { console.log('error_F1', e); reject(e); } resolve(res); }).catch(console.warn); }); }; return pipelineExecution; } 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 insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0); const prototypeInherit = (d, b) => { const m = Object.getOwnPropertyDescriptors(b); for (const p in m) { if (!Object.getOwnPropertyDescriptor(d, p)) { Object.defineProperty(d, p, m[p]); } } }; let setTimeout_ = setTimeout; let clearTimeout_ = clearTimeout; const delayPn = delay => new Promise((fn => setTimeout_(fn, delay))); const isWatchPageURL = (url) => { url = url || location; return location.pathname === '/watch' || location.pathname.startsWith('/live/') }; const mockEvent = (o, elem) => { o = o || {}; elem = elem || null; return { preventDefault: () => { }, stopPropagation: () => { }, stopImmediatePropagation: () => { }, returnValue: true, target: elem, srcElement: elem, defaultPrevented: false, cancelable: true, timeStamp: performance.now(), ...o } }; const generalRegister = (prop, symbol, checker, pg) => { const objSet = new Set(); let done = false; const f = (o) => { const ct = o.constructor; const proto = ct.prototype; if (!done && proto && ct !== Function && ct !== Object && checker(proto)) { done = true; delete Object.prototype[prop]; objSet.delete(proto); objSet.delete(o); for (const obj of objSet) { obj[prop] = obj[symbol]; delete obj[symbol]; } objSet.clear(); Object.defineProperty(proto, prop, pg); return proto; } return false; }; Object.defineProperty(Object.prototype, prop, { get() { const p = f(this); if (p) { return p[prop]; } else { return this[symbol]; } }, set(nv) { const p = f(this); if (p) { p[prop] = nv; } else { objSet.add(this); this[symbol] = nv; } return true; }, enumerable: false, configurable: true }); }; const mediaNetworkStateReady = async (audio) => { if (!(audio instanceof HTMLMediaElement)) { return ''; } let done = false; const et = await Promise.race([ new Promise(resolve => { audio.addEventListener('timeupdate', (evt) => { !done && resolve && resolve(evt.type); resolve = null }, { once: true, capture: true, passive: true }) }), new Promise(resolve => { audio.addEventListener('waiting', (evt) => { !done && resolve && resolve(evt.type); resolve = null }, { once: true, capture: true, passive: true }) }), new Promise(resolve => { audio.addEventListener('loadstart', (evt) => { !done && resolve && resolve(evt.type); resolve = null }, { once: true, capture: true, passive: true }) }), new Promise(resolve => { audio.addEventListener('durationchange', (evt) => { !done && resolve && resolve(evt.type); resolve = null }, { once: true, capture: true, passive: true }) }) ]); done = true; return et; }; const updateLastActiveTimeAsync = (player_) => { // TBC Promise.resolve().then(() => { if (typeof player_.updateLastActiveTime === 'function') { player_.updateLastActiveTime(); } }); }; const attachOneTimeEvent = function (eventType, callback) { let kz = false; document.addEventListener(eventType, function (evt) { if (kz) return; kz = true; callback(evt); }, { capture: true, passive: true, once: true }); } function removeTempObjectProp01() { delete Object.prototype['kevlar_non_watch_unified_player']; delete Object.prototype['kevlar_unified_player']; } function ytConfigFix(config__) { const config_ = config__; if (config_) { const playerKevlar = ((config_ || 0).WEB_PLAYER_CONTEXT_CONFIGS || 0).WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH || 0; if (playerKevlar) { // console.log(322, playerKevlar) playerKevlar.allowWoffleManagement = false; playerKevlar.cinematicSettingsAvailable = false; playerKevlar.showMiniplayerButton = false; playerKevlar.showMiniplayerUiWhenMinimized = false; playerKevlar.transparentBackground = false; playerKevlar.enableCsiLogging = false; playerKevlar.externalFullscreen = false; if (typeof playerKevlar.serializedExperimentFlags === 'string') { playerKevlar.serializedExperimentFlags = ''; // playerKevlar.serializedExperimentFlags = playerKevlar.serializedExperimentFlags.replace(/[-\w]+=(\[\]|[.-\d]+|[_a-z]+|)(&|$)/g,'').replace(/&$/,'') } if (typeof playerKevlar.serializedExperimentIds === 'string') { playerKevlar.serializedExperimentIds = ''; // playerKevlar.serializedExperimentIds = playerKevlar.serializedExperimentIds.replace(/\d+\s*(,\s*|$)/g,'') } } removeTempObjectProp01(); let configs = config_.WEB_PLAYER_CONTEXT_CONFIGS || {}; for (const [key, entry] of Object.entries(configs)) { if (entry && typeof entry.serializedExperimentFlags === 'string' && entry.serializedExperimentFlags.length > 16) { // prevent idle playback failure entry.serializedExperimentFlags = entry.serializedExperimentFlags.replace(/\b(html5_check_for_idle_network_interval_ms|html5_trigger_loader_when_idle_network|html5_sabr_fetch_on_idle_network_preloaded_players|html5_autonav_cap_idle_secs|html5_autonav_quality_cap|html5_disable_client_autonav_cap_for_onesie|html5_idle_rate_limit_ms|html5_sabr_fetch_on_idle_network_preloaded_players|html5_webpo_idle_priority_job|html5_server_playback_start_policy|html5_check_video_data_errors_before_playback_start|html5_check_unstarted|html5_check_queue_on_data_loaded)=([-_\w]+)(\&|$)/g, (_, a, b, c) => { return a + '00' + '=' + b + c; }); } } const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS; if (EXPERIMENT_FLAGS) { EXPERIMENT_FLAGS.kevlar_unified_player = true; EXPERIMENT_FLAGS.kevlar_non_watch_unified_player = true; } const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS; if (EXPERIMENTS_FORCED_FLAGS) { EXPERIMENTS_FORCED_FLAGS.kevlar_unified_player = true; EXPERIMENTS_FORCED_FLAGS.kevlar_non_watch_unified_player = true; } } } Object.defineProperty(Object.prototype, 'kevlar_non_watch_unified_player', { get() { // console.log(501, this.constructor.prototype) return true; }, set(nv) { return true; }, enumerable: false, configurable: true }); Object.defineProperty(Object.prototype, 'kevlar_unified_player', { get() { // console.log(501, this.constructor.prototype) return true; }, set(nv) { return true; }, enumerable: false, configurable: true }); let prr = new PromiseExternal(); const prrPipeline = createPipeline(); let stopAndReload = false; let fa = 0; let cv = null; let durationchangeForMobile = false; function fixThumbnailURL(src) { if (typeof src === 'string' && src.length >= 4) { let m = /\b[a-z0-9]{4,13}\.jpg\b/.exec(src); if (m && m[0]) { const t = m[0]; let idx = src.indexOf(t); let nSrc = idx >= 0 ? src.substring(0, idx + t.length) : ''; return nSrc; } } return src; } const isDesktopSite = location.origin === 'https://www.youtube.com' && !location.pathname.startsWith('/embed/'); const getThumbnailUrlFromThumbnails = (thumbnails) => { let thumbnailUrl = ''; if (thumbnails && thumbnails.length >= 1) { const arr = thumbnails.map(e => { return e.url ? [e.width * e.height, e.url] : typeof e === 'string' ? [0, e] : [0, ''] }); arr.sort((a, b) => b[0] - a[0]); thumbnailUrl = arr[0][1] if (typeof thumbnailUrl === 'string') { thumbnailUrl = fixThumbnailURL(thumbnailUrl); } } return thumbnailUrl; } const pmof = () => { if (SHOW_VIDEO_STATIC_IMAGE) { const medias = [...document.querySelectorAll('ytd-watch-flexy #player .html5-video-container .video-stream.html5-main-video')].filter(e => !e.closest('[hidden]')); if (medias.length !== 1) return; const mediaElement = medias[0]; const container = mediaElement ? mediaElement.closest('.html5-video-container') : null; if (!container) return; let thumbnailUrl = ''; const ytdPage = container.closest('ytd-watch-flexy'); if (ytdPage && ytdPage.is === 'ytd-watch-flexy') { const cnt = insp(ytdPage); let thumbnails = null; try { thumbnails = cnt.polymerController.__data.playerData.videoDetails.thumbnail.thumbnails // thumbnails = cnt.__data.watchNextData.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer.background.thumbnails } catch (e) { } thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails); } if (thumbnailUrl && typeof thumbnailUrl === 'string') { container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`); } else { container.style.removeProperty('--audio-only-thumbnail-image') } } } const pmo = new MutationObserver(pmof); isDesktopSite && document.addEventListener('yt-navigate-finish', () => { const ytdWatchFlexy = document.querySelector('ytd-watch-flexy'); if (ytdWatchFlexy) { pmo.observe(ytdWatchFlexy, { attributes: true }); ytdWatchFlexy.setAttribute('ytzNavigateFinish', Date.now()); } }); document.addEventListener('durationchange', (evt) => { const target = (evt || 0).target; if (!(target instanceof HTMLMediaElement)) return; const targetClassList = target.classList || 0; const isPlayerVideo = typeof targetClassList.contains === 'function' ? targetClassList.contains('video-stream') && targetClassList.contains('html5-main-video') : false; if (durationchangeForMobile || isPlayerVideo) { if (target.readyState !== 1) { fa = 1; } else { fa = 2; } } if (isPlayerVideo) { if (target.readyState === 1 && target.networkState === 2) { target.__spfgs__ = true; if (cv) { cv.resolve(); cv = null; } } else { target.__spfgs__ = false; } if (isDesktopSite) { const ytdWatchFlexy = document.querySelector('ytd-watch-flexy'); if (ytdWatchFlexy) { ytdWatchFlexy.setAttribute('ytzMediaDurationChanged', Date.now()); } } if (onVideoChangeForMobile) { onVideoChangeForMobile(); } } }, true); // XMLHttpRequest.prototype.open299 = XMLHttpRequest.prototype.open; /* XMLHttpRequest.prototype.open2 = function(method, url, ...args){ if (typeof url === 'string' && url.length > 24 && url.includes('/videoplayback?') && url.replace('?', '&').includes('&source=')) { if (vcc !== vdd) { vdd = vcc; window.postMessage({ ZECxh: url.includes('source=yt_live_broadcast') }, "*"); } } return this.open299(method, url, ...args) }*/ // desktop only // document.addEventListener('yt-page-data-fetched', async (evt) => { // const pageFetchedDataLocal = evt.detail; // let isLiveNow; // try { // isLiveNow = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.isLiveNow; // } catch (e) { } // window.postMessage({ ZECxh: isLiveNow === true }, "*"); // }, false); // return; // let clickLockFn = null; let onVideoChangeForMobile = null; let removeBottomOverlayForMobile = null; let clickLockFn = null; let clickTarget = null; if (location.origin === 'https://m.youtube.com') { EventTarget.prototype.addEventListener322 = EventTarget.prototype.addEventListener; const dummyFn = () => { }; EventTarget.prototype.addEventListener = function (evt, fn, opts) { let hn = fn; // if (evt === 'player-error') { // } else if (evt === 'player-detailed-error') { // } else if (evt === 'video-data-change') { // } else if (evt === 'player-state-change') { // } else if (evt === 'player-autonav-pause' || evt === 'visibilitychange') { evt += 'y' fn = dummyFn; } else if (evt === 'click' && this.id === 'movie_player') { clickLockFn = fn; clickTarget = this; } return this.addEventListener322(evt, hn, opts) } } (() => { XMLHttpRequest = (() => { const XMLHttpRequest_ = XMLHttpRequest; if ('__xmMc8__' in XMLHttpRequest_.prototype) return XMLHttpRequest_; const url0 = createObjectURL(new Blob([], { type: 'text/plain' })); const c = class XMLHttpRequest extends XMLHttpRequest_ { constructor(...args) { super(...args); } open(method, url, ...args) { let skip = false; if (!url || typeof url !== 'string') skip = true; else if (typeof url === 'string') { let turl = url[0] === '/' ? `.youtube.com${url}` : `${url}`; if (turl.includes('googleads') || turl.includes('doubleclick.net')) { skip = true; } else if (turl.includes('.youtube.com/pagead/')) { skip = true; } else if (turl.includes('.youtube.com/ptracking')) { skip = true; } else if (turl.includes('.youtube.com/api/stats/')) { // /api/stats/ // skip = true; // for user activity logging e.g. watched videos } else if (turl.includes('play.google.com/log')) { skip = true; } else if (turl.includes('.youtube.com//?')) { // //?cpn= skip = true; } } if (!skip) { this.__xmMc8__ = 1; return super.open(method, url, ...args); } else { this.__xmMc8__ = 2; return super.open('GET', url0); } } send(...args) { if (this.__xmMc8__ === 1) { return super.send(...args); } else if (this.__xmMc8__ === 2) { return super.send(); } else { console.log('xhr warning'); return super.send(...args); } } } c.prototype.__xmMc8__ = 0; prototypeInherit(c.prototype, XMLHttpRequest_.prototype); return c; })(); const s7 = Symbol(); const f7 = () => true; !window.canRetry9048 && generalRegister('canRetry', s7, (p) => { return typeof p.onStateChange === 'function' && typeof p.dispose === 'function' && typeof p.hide === 'undefined' && typeof p.show === 'undefined' && typeof p.isComplete === 'undefined' && typeof p.getDuration === 'undefined' }, { get() { if ('logger' in this && 'policy' in this && 'xhr' && this) { if (this.errorMessage && typeof this.errorMessage === 'string' && this.errorMessage.includes('XMLHttpRequest') && this.errorMessage.includes('Invalid URL')) { // "SyntaxError_Failed to execute 'open' on 'XMLHttpRequest': Invalid URL" // OKAY ! console.log('canRetry05 - ', this.errorMessage) return f7; } // console.log(this) console.log('canRetry02 - ', this.errorMessage, this) } else { console.log('canRetry ERR - ', this.errorMessage) } return this[s7]; }, set(nv) { this[s7] = nv; return true; }, enumerable: false, configurable: true }); window.canRetry9048 = 1; })(); if (location.origin === 'https://www.youtube.com') { if (location.pathname.startsWith('/embed/')) { const ytEmbedReady = observablePromise(() => document.querySelector('#player > .ytp-embed')).obtain(); const embedConfigFix = (async () => { while (true) { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; if (config_) { ytConfigFix(config_); break; } await delayPn(60); } }); ytEmbedReady.then(async (embedPlayer) => { embedConfigFix(); const player_ = embedPlayer; // console.log(player_) const asyncStateChange = async (audio, k) => { const refreshAllStaleEntitiesForNonReadyAudio = async () => { try { if (audio.readyState == 0) await player_.refreshAllStaleEntities(); } catch (e) { } }; const triggerPlaying = async () => { await player_.pauseVideo(); await player_.playVideo(); }; const seekToLiveHeadForLiveStream = async () => { try { await player_.seekToLiveHead(); if ((await player_.isAtLiveHead()) === true) { await player_.seekToStreamTime(); return true; } } catch (e) { console.log('error_F3', e); } }; const fixLiveAudioFn = async () => { if (audio.paused === true) { await player_.clearVideo(); // avoid error in live streaming await player_.clearQueue(); // avoid error in live streaming await delayPn(300); for (let i = 0; i < 3; i++) { if (audio.readyState === 0) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } } if (k === -1) { await refreshAllStaleEntitiesForNonReadyAudio(); } else if (k === 3) { while (audio.readyState === 0) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } } } else if (audio.paused === false) { if (!player_.isAtLiveHead()) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } while (audio.readyState === 0) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } if (!player_.isAtLiveHead()) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } await refreshAllStaleEntitiesForNonReadyAudio(); if (audio.readyState > 0 && audio.paused === true) { await triggerPlaying(); } } } try { let ns23 = audio.networkState == 2 || audio.networkState == 3; if (!ns23 && k === player_.getPlayerState()) { if (k === -1 && audio.readyState === 0) { const et = await mediaNetworkStateReady(audio); if (audio.isConnected === false || player_.getPlayerState() === 5) return; ns23 = audio.networkState == 2 || audio.networkState == 3; // console.log(503, ns23, et, player_.getPlayerState()); if (player_.getPlayerState() !== -1) return; } else { console.log(507, k, audio.readyState, audio.networkState) } } if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { await delayPn(200); if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { await fixLiveAudioFn(); } } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) { await seekToLiveHeadForLiveStream(); } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) { await delayPn(60); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) { await fixLiveAudioFn(); } } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) { await seekToLiveHeadForLiveStream(); } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) { await delayPn(60); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) { await fixLiveAudioFn(); } } } catch (e) { console.log('error_F4', e) } }; // console.log(299, player_) const _onPlayerStateChange = (k) => { try { if (typeof k === 'number' && k === player_.getPlayerState()) { const audio = document.querySelector('#player audio.video-stream.html5-main-video'); if (audio) asyncStateChange(audio, k); } } catch (e) { console.log('error_F5', e) } }; player_.addEventListener('onStateChange', _onPlayerStateChange); const state0 = player_.getPlayerState(); if (typeof state0 === 'number') { _onPlayerStateChange(state0); } player_.addEventListener('onVideoProgress', () => { updateLastActiveTimeAsync(player_); }); // console.log(1231) if (SHOW_VIDEO_STATIC_IMAGE) { let displayImage = ''; let html5Container = null; const moviePlayer = document.querySelector('#movie_player .html5-video-container .video-stream.html5-main-video'); if (moviePlayer) { html5Container = moviePlayer.closest('.html5-video-container'); } if (html5Container) { const overlayImage = document.querySelector('#movie_player .ytp-cued-thumbnail-overlay-image[style]'); if (overlayImage) { const cStyle = window.getComputedStyle(overlayImage); const cssImageValue = cStyle.backgroundImage; if (cssImageValue && typeof cssImageValue === 'string' && cssImageValue.startsWith('url(')) { displayImage = cssImageValue; } } if (!displayImage) { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; let embedded_player_response = null; if (config_) { embedded_player_response = ((config_.PLAYER_VARS || 0).embedded_player_response || 0) } if (embedded_player_response && typeof embedded_player_response === 'string') { let idx1 = embedded_player_response.indexOf('"defaultThumbnail"'); let idx2 = idx1 >= 0 ? embedded_player_response.lastIndexOf('"defaultThumbnail"') : -1; if (idx1 === idx2 && idx1 > 0) { let bk = 0; let j = -1; for (let i = idx1; i < embedded_player_response.length; i++) { if (i > idx1 + 40 && bk === 0) { j = i; break; } let t = embedded_player_response.charAt(i); if (t === '{') bk++; else if (t === '}') bk--; } if (j > idx1) { let defaultThumbnailString = embedded_player_response.substring(idx1, j); let defaultThumbnailObject = null; try { defaultThumbnailObject = JSON.parse(`{${defaultThumbnailString}}`); } catch (e) { } const thumbnails = ((defaultThumbnailObject.defaultThumbnail || 0).thumbnails || 0); if (thumbnails && thumbnails.length >= 1) { let thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails); if (thumbnailUrl && thumbnailUrl.length > 3) { displayImage = `url(${thumbnailUrl})`; } } } } } } if (displayImage) { html5Container.style.setProperty('--audio-only-thumbnail-image', `${displayImage}`); } else { html5Container.style.removeProperty('--audio-only-thumbnail-image') } } } }); } else { attachOneTimeEvent('yt-action', () => { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; ytConfigFix(config_); }); const setupAudioPlaying = (player00_) => { const player_ = player00_; if (!player_) return; if (player_.__audio544__) return; player_.__audio544__ = 1; globalPlayer = mWeakRef(player_); // console.log(1233, player_) const mediaCollection = document.getElementsByClassName('html5-main-video'); const stopAndReloadFn = async () => { let isLive = false; if (isWatchPageURL()) { const liveBtn = document.querySelector('.ytp-live-badge.ytp-button'); try { if (liveBtn && !liveBtn.closest('[hidden]') && (liveBtn.textContent || '').trim().length > 0) { isLive = true; } } catch (e) { } } if (isLive) { player_.destroy(); location.replace(location.href); await delayPn(8000); } else { // await player_.stopVideo(); // await player_.updateVideoData(); // try{ // await player_.refreshAllStaleEntities(); // }catch(e){} // await player_.playVideo(); } }; const asyncStateChange = async (audio, k) => { const refreshAllStaleEntitiesForNonReadyAudio = async () => { try { if (audio.readyState == 0 && audio.isConnected === true) await player_.refreshAllStaleEntities(); } catch (e) { } }; const triggerPlaying = async () => { await player_.cancelPlayback(); await player_.pauseVideo(); await player_.playVideo(); }; const seekToLiveHeadForLiveStream = async () => { try { audio.isConnected === true && await player_.seekToLiveHead(); if (audio.isConnected === true && (await player_.isAtLiveHead()) === true) { audio.isConnected === true && await player_.seekToStreamTime(); return true; } } catch (e) { console.log('error_F7', e); } }; const fixLiveAudioFn = async () => { if (stopAndReload) { stopAndReload = false; await stopAndReloadFn(); } if (audio.isConnected === true && audio.paused === true) { await player_.clearVideo(); // avoid error in live streaming await player_.clearQueue(); // avoid error in live streaming await delayPn(300); for (let i = 0; i < 3; i++) { if (audio.readyState === 0 && audio.isConnected === true) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } } if (k === -1) { await refreshAllStaleEntitiesForNonReadyAudio(); } else if (k === 3) { while (audio.readyState === 0 && audio.isConnected === true) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } } } else if (audio.isConnected === true && audio.paused === false) { if (!player_.isAtLiveHead() && audio.isConnected === true) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } while (audio.readyState === 0 && audio.isConnected === true) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } if (!player_.isAtLiveHead() && audio.isConnected === true) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } await refreshAllStaleEntitiesForNonReadyAudio(); if (audio.readyState > 0 && audio.paused === true && audio.isConnected === true) { await triggerPlaying(); } } } try { let ns23 = audio.networkState == 2 || audio.networkState == 3; if (!ns23 && k === player_.getPlayerState()) { if (k === -1 && audio.readyState === 0) { const et = await mediaNetworkStateReady(audio); if (audio.isConnected === false || player_.getPlayerState() === 5) return; ns23 = audio.networkState == 2 || audio.networkState == 3; console.log(513, ns23, et, player_.getPlayerState()); if (player_.getPlayerState() !== -1) return; } else if (k === 3 && audio.readyState === 0 && audio.networkState === 0) { const et = await Promise.race([mediaNetworkStateReady(audio), delayPn(800)]); // idk if (audio.isConnected === false || player_.getPlayerState() === 5) return; ns23 = audio.networkState == 2 || audio.networkState == 3; console.log(514, ns23, et, player_.getPlayerState()); if (player_.getPlayerState() !== 3) return; } else { console.log(517, k, audio.readyState, audio.networkState) // 517 3 0 0 after tab sleeping } } if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { await delayPn(200); if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { await fixLiveAudioFn(); } } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) { await seekToLiveHeadForLiveStream(); } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) { await delayPn(60); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) { await fixLiveAudioFn(); } } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) { await seekToLiveHeadForLiveStream(); } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) { await delayPn(60); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) { await fixLiveAudioFn(); } } } catch (e) { console.log('error_F8', e) } }; let mid = 0; const getAudioElement = () => { if (mediaCollection.length === 0) return null; if (mediaCollection.length > 1) { const audios = [...mediaCollection].filter(e => e && !e.closest('[hidden]') && e.closest('ytd-player')); if (audios.length === 1) { return audios[0]; } } else if (mediaCollection.length === 1) { const e = mediaCollection[0]; if (e && !e.closest('[hidden]') && e.closest('ytd-player')) return e; } return null; }; const _onPlayerStateChange = (k_) => { const k = k_; const ps = player_.getPlayerState(); if (stopAndReload) { stopAndReload = false; const audio = getAudioElement(); if (audio) { prrPipeline(async () => { await prr.then(); await stopAndReloadFn(); }); } } if (typeof k === 'number' && k === ps && ps !== 5) { if (mid > 1e9) mid = 9; const t = ++mid; prrPipeline(async () => { if (t !== mid) return; await prr.then(); if (t !== mid) return; const audio = getAudioElement(); if (audio && player_.getPlayerState() === ps) { await asyncStateChange(audio, k); } }); } }; player_.addEventListener('onStateChange', _onPlayerStateChange); const state0 = player_.getPlayerState(); // console.log(221, state0) if (typeof state0 === 'number') { _onPlayerStateChange(state0); } player_.addEventListener('onVideoProgress', () => { updateLastActiveTimeAsync(player_); }); } customElements.whenDefined('ytd-player').then(() => { const dummy = document.querySelector('ytd-player') || document.createElement('ytd-player'); const cnt = insp(dummy); const cProto = cnt.constructor.prototype; cProto.createMainAppPlayer932_ = cProto.createMainAppPlayer_; cProto.initPlayer932_ = cProto.initPlayer_; const configFixBeforeCreate = () => { try { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; if (config_) { ytConfigFix(config_); } } catch (e) { } } cProto.createMainAppPlayer_ = function (a, b, c) { configFixBeforeCreate(); let r = this.createMainAppPlayer932_(a, b, c); try { this.mainAppPlayer_.api.then(function (e) { setupAudioPlaying(e); }) } finally { return r; } } cProto.initPlayer_ = function (a) { configFixBeforeCreate(); let r = this.initPlayer932_(a); try { r.then(() => { setupAudioPlaying(this.player_); }) } finally { return r; } } }) let useStopAndReload = !isWatchPageURL(); document.addEventListener('yt-navigate-start', () => { prr = new PromiseExternal(); if (useStopAndReload) stopAndReload = true; }); document.addEventListener('yt-navigate-cache', () => { prr = new PromiseExternal(); if (useStopAndReload) stopAndReload = true; }); document.addEventListener('yt-navigate-finish', () => { prr.resolve(); }); } } else if (location.origin === 'https://m.youtube.com') { removeBottomOverlayForMobile = async (delay) => { let closeBtnRenderer = document.querySelector('.ytm-bottom-sheet-overlay-renderer-close.icon-close'); if (closeBtnRenderer) { const btn = closeBtnRenderer.querySelector('button'); const container = closeBtnRenderer.closest('#global-loader ~ .ytm-bottom-sheet-overlay-container'); if (container) { container.style.visibility = 'collapse'; container.style.zIndex = '-1'; } if (btn) { if (delay) { await delayPn(delay); } btn.click(); } } } const getAppJSON = () => { let t; t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]'); if (t) return t; t = document.querySelector('player-microformat-renderer.playerMicroformatRendererHost script[type="application/ld+json"]'); if (t) return t; console.log('[mobile youtube audio only] getAppJSON fails.', document.querySelectorAll('script[type="application/ld+json"]').length); return null; } let lastPlayerInfoText = ''; let mz = 0; onVideoChangeForMobile = async () => { let html5Container = null; const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video'); if (moviePlayer) { html5Container = moviePlayer.closest('.html5-video-container'); } console.log('STx00', html5Container) if (!html5Container) return; let thumbnailUrl = ''; if (mz > 1e9) mz = 9; let mt = ++mz; const scriptText = await observablePromise(() => { if (mt !== mz) return 1; const t = getAppJSON(); const tt = (t ? t.textContent : '') || ''; if (tt === lastPlayerInfoText) return; return tt; }).obtain(); if (typeof scriptText !== 'string') return; // 1 lastPlayerInfoText = scriptText; if (!scriptText) return; if (SHOW_VIDEO_STATIC_IMAGE) { console.log('STx01') let idx1 = scriptText.indexOf('"thumbnailUrl"'); let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1; if (idx1 === idx2 && idx1 > 0) { let bk = 0; let j = -1; for (let i = idx1; i < scriptText.length; i++) { if (i > idx1 + 20 && bk === 0) { j = i; break; } let t = scriptText.charAt(i); if (t === '[') bk++; else if (t === ']') bk--; else if (t === '{') bk++; else if (t === '}') bk--; } if (j > idx1) { let thumbnailUrlString = scriptText.substring(idx1, j); let thumbnailUrlObject = null; try { thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`); } catch (e) { } const thumbnails = thumbnailUrlObject.thumbnailUrl; if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') { if (thumbnails[0] && thumbnails[0].length > 3) { thumbnailUrl = thumbnails[0]; } } } } console.log('STx02', thumbnailUrl) // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0; // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0); // if (thumbnails && thumbnails.length >= 1) { // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails); // } if (thumbnailUrl && typeof thumbnailUrl === 'string') { html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`); } else { html5Container.style.removeProperty('--audio-only-thumbnail-image') } } if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40); await delayPn(80); const audio = moviePlayer; if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) { await audio.click(); } } let player0 = null; let mgg = null; const mff = function (e) { if (!player0) { if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') { player0 = e.target if (mgg) mgg(); } } // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) { // onVideoChangeForMobile(); // } } document.addEventListener('player-initialized', mff, true); document.addEventListener('player-state-change', mff, true); document.addEventListener('player-ad-state-change', mff, true); document.addEventListener('player-detailed-error', mff, true); document.addEventListener('player-error', mff, true); document.addEventListener('on-play-autonav-video', mff, true); document.addEventListener('on-play-previous-autonav-video', mff, true); document.addEventListener('player-fullscreen-change', mff, true); document.addEventListener('player-fullscreen-toggled', mff, true); document.addEventListener('player-dom-paused', mff, true); document.addEventListener('yt-show-toast', mff, true); document.addEventListener('yt-innertube-command', mff, true); document.addEventListener('yt-update-c3-companion', mff, true); document.addEventListener('video-data-change', mff, true); document.addEventListener('video-progress', mff, true); document.addEventListener('local-media-change', mff, true); let tc = false; // let pw = null; (async () => { let player__; const getAudioElement = () => { const elm = player__ || player0; const audio = elm && elm.isConnected === true ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null; return audio; } const asyncStateChange = async (audio, k) => { const player_ = player__; if (!player_) return; if (typeof player_.getPlayerState !== 'function') return; const refreshAllStaleEntitiesForNonReadyAudio = async () => { // try { // if (audio.readyState == 0) await player_.refreshAllStaleEntities(); // } catch (e) { // } }; const triggerPlaying = async () => { await player_.cancelPlayback(); await player_.pauseVideo(); await player_.playVideo(); }; const seekToLiveHeadForLiveStream = async () => { try { await player_.seekToLiveHead(); if ((await player_.isAtLiveHead()) === true) { await player_.seekToStreamTime(); return true; } } catch (e) { console.log('error_F9', e); } }; const fixLiveAudioFn = async () => { if (audio.paused === true) { await player_.clearVideo(); // avoid error in live streaming await player_.clearQueue(); // avoid error in live streaming await delayPn(300); for (let i = 0; i < 3; i++) { if (audio.readyState === 0) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } } if (k === -1) { await refreshAllStaleEntitiesForNonReadyAudio(); } else if (k === 3) { while (audio.readyState === 0) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } // console.log(8809,audio.readyState) } } else if (audio.paused === false) { if (!player_.isAtLiveHead()) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } while (audio.readyState === 0) { await refreshAllStaleEntitiesForNonReadyAudio(); await triggerPlaying(); await delayPn(300); } if (!player_.isAtLiveHead()) { if (await seekToLiveHeadForLiveStream()) await delayPn(60); } await refreshAllStaleEntitiesForNonReadyAudio(); if (audio.readyState > 0 && audio.paused === true) { await triggerPlaying(); } } } try { let ns23 = audio.networkState == 2 || audio.networkState == 3 // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted) if (!ns23 && k === player_.getPlayerState()) { if (k === -1 && audio.readyState === 0) { const et = await mediaNetworkStateReady(audio); if (audio.isConnected === false || player_.getPlayerState() === 5) return; ns23 = audio.networkState == 2 || audio.networkState == 3; console.log(523, ns23, et, player_.getPlayerState()); if (player_.getPlayerState() !== -1) return; } else { console.log(527, k, audio.readyState, audio.networkState) } } if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) { tc = true; } if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { await delayPn(200); if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) { // console.log(8806) await fixLiveAudioFn(); } } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) { await seekToLiveHeadForLiveStream(); } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) { await delayPn(60); if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) { // console.log(8807) await fixLiveAudioFn(); } } } catch (e) { console.log('error_F10', e) } }; const _onPlayerStateChange = (e) => { if (e && (e || 0).target) { player__ = e.target } const player_ = player__; try { if (!player_) return; let k = null; if (e && e.detail && e.detail.state) { k = e.detail.state } if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) { const audio = getAudioElement(); if (audio) asyncStateChange(audio, k); } } catch (e) { console.log('error_F11', e) } }; let idleAudioActivatePending = false; const _onVideoProgress = (e) => { if (e && (e || 0).target) { player__ = e.target } const player_ = player__; if (!player_) return; updateLastActiveTimeAsync(player_); if (tc) { tc = false; if (!idleAudioActivatePending) { idleAudioActivatePending = true; } } }; mgg = function () { const player_ = player0; if (player_) { const state0 = player_.getPlayerState(); if (typeof state0 === 'number') { _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } }); } } } document.addEventListener('player-state-change', _onPlayerStateChange, true); document.addEventListener('video-progress', _onVideoProgress, true); })(); // document.addEventListener('DOMContentLoaded', (evt) => { // const mo = new MutationObserver((mutations)=>{ // console.log(5899, mutations) // }); // mo.observe(document, {subtree: true, childList: true}) // }) // window.addEventListener('onReady', (evt) => { // console.log(6811) // }, true); // window.addEventListener('localmediachange', (evt) => { // console.log(6812) // }, true); // window.addEventListener('onVideoDataChange', (evt) => { // console.log(6813) // }, true); window.addEventListener('state-navigateend', async (evt) => { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; ytConfigFix(config_); try { if (clickLockFn && clickTarget) { let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video'); if (!a) return; if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) { const pr = new Promise(resolve => { document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false }); }).then(); clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 })); await delayPn(1); if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) { clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 })); await delayPn(1); } delayRun(pr); } } } catch (e) { console.log('error_F12', e) } }, false); // document.addEventListener('volumechange', (evt) => { // console.log('volumechange') // }, true) // document.addEventListener('play', (evt) => { // console.log('play') // }, true) // document.addEventListener('player-initialized', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('renderer-module-load-start', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('video-data-change', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-state-change', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('updateui', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('renderer-module-load-end', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-autonav-pause', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-ad-state-change', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-detailed-error', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-error', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('on-play-autonav-video', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('on-play-previous-autonav-video', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-fullscreen-change', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-fullscreen-toggled', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-dom-paused', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('yt-show-toast', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('yt-innertube-command', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('yt-update-c3-companion', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('video-progress', (evt) => { // // console.log(evt.type) // }, true) // document.addEventListener('localmediachange', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-initialized', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('renderer-module-load-start', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('video-data-change', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-state-change', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('updateui', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('renderer-module-load-end', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-autonav-pause', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-ad-state-change', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-detailed-error', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-error', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('on-play-autonav-video', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('on-play-previous-autonav-video', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-fullscreen-change', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-fullscreen-toggled', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('player-dom-paused', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('yt-show-toast', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('yt-innertube-command', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('yt-update-c3-companion', (evt) => { // console.log(evt.type) // }, true) // window.addEventListener('video-progress', (evt) => { // // console.log(evt.type) // }, true) // window.addEventListener('localmediachange', (evt) => { // console.log(evt.type) // }, true) // document.addEventListener('player-error', (evt) => { // console.log(3001, evt.type, evt) // }, true) // document.addEventListener('player-detailed-error', (evt) => { // console.log(3002, evt.type, evt) // }, true) async function delayRun(pr) { let q = document.querySelector('#movie_player'); if (!q) return; let a = document.querySelector('.video-stream.html5-main-video'); if (!a) return; await pr.then(); if (fa !== 1) { return; } else if (a.muted === true) { return; } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) { if (a.paused === false) return; } else { return; } if (document.querySelector('.player-controls-content')) return; if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) { clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 })); } if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) { if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead(); if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) { if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime(); } } } durationchangeForMobile = true; } attachOneTimeEvent('yt-action', function () { const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0; ytConfigFix(config_); }); let prepared = false; function prepare() { if (prepared) return; prepared = true; if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') { for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.clone === 'function' && typeof p.get === 'function' && typeof p.set === 'function' && typeof p.isEmpty === 'undefined' && typeof p.forEach === 'undefined' && typeof p.clear === 'undefined' ) { key = k; } } } if (key) { const ClassX = _yt_player[key]; _yt_player[key] = class extends ClassX { constructor(...args) { if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = ''; super(...args); } } _yt_player[key].luX1Y = 1; prototypeInherit(_yt_player[key].prototype, ClassX.prototype); } } let s3 = Symbol(); generalRegister('deviceIsAudioOnly', s3, (p) => { return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p) }, { get() { return this[s3]; }, set(nv) { if (typeof nv === 'boolean') this[s3] = true; else this[s3] = undefined; prepare(); return true; }, enumerable: false, configurable: true }); let s1 = Symbol(); let s2 = Symbol(); Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', { get() { // console.log(501, this.constructor.prototype) return undefined; }, set(nv) { return true; }, enumerable: false, configurable: true }); Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', { get() { // console.log(502, this.constructor.prototype) return this[s1]; }, set(nv) { if (typeof nv === 'boolean') this[s1] = false; else this[s1] = undefined; return true; }, enumerable: false, configurable: true }); Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', { get() { // console.log(503, this.constructor.prototype) return this[s2]; }, set(nv) { if (typeof nv === 'boolean') this[s2] = false; else this[s2] = undefined; return true; }, enumerable: false, configurable: true }); const supportedFormatsConfig = () => { function typeTest(type) { if (typeof type === 'string' && type.startsWith('video/')) { return false; } } // return a custom MIME type checker that can defer to the original function function makeModifiedTypeChecker(origChecker) { // Check if a video type is allowed return function (type) { let res = undefined; if (type === undefined) res = false; else { res = typeTest.call(this, type); } if (res === undefined) res = origChecker.apply(this, arguments); return res; }; } // Override video element canPlayType() function const proto = (HTMLVideoElement || 0).prototype; if (proto && typeof proto.canPlayType == 'function') { proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType); } // Override media source extension isTypeSupported() function const mse = window.MediaSource; // Check for MSE support before use if (mse && typeof mse.isTypeSupported == 'function') { mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported); } }; supportedFormatsConfig(); PATCH_MEDIA_PUBLISH && (async ()=>{ const _yt_player_observable = observablePromise(() => { return (((window || 0)._yt_player || 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 getD0 = (_yt_player) => { const w = 'D0'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.playVideo === 'function' && p.playVideo.length === 1 && typeof p.getVisibilityState === 'function' && p.getVisibilityState.length === 8 && typeof p.getVideoData === 'function' && p.getVideoData.length === 0 && typeof p.seekTo === 'function' && p.seekTo.length === 5 && typeof p.pauseVideo === 'function' && p.pauseVideo.length === 2 && typeof p.stopVideo === 'function' && p.stopVideo.length === 1 && typeof p.getPresentingPlayerType === 'function' && p.getPresentingPlayerType.length === 1 && typeof p.getCurrentTime === 'function' && p.getCurrentTime.length === 3 && typeof p.cancelPlayback === 'function' && p.cancelPlayback.length === 2 // && !p.getPlayerType ) { 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 gets0 = (_yt_player) => { const w = 's0'; let arr = []; for (const [k, v] of Object.entries(_yt_player)) { const p = typeof v === 'function' ? v.prototype : 0; if (p && typeof p.isBackground === 'function' && p.isBackground.length === 0 && typeof p.getPlaybackRate === 'function' && p.getPlaybackRate.length === 0 && typeof p.publish === 'function' && p.publish.length === 2 && typeof p.isAtLiveHead === 'function' && p.isAtLiveHead.length === 2 // && !p.getPlayerType ) { 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 printObject = (b)=>{ return JSON.stringify( Object.entries(b||{}).filter(e=>typeof (e[1]||0)!=='object')); }; /* (async () => { // rAf scheduling const _yt_player = await _yt_player_observable.obtain(); if (!_yt_player || typeof _yt_player !== 'object') return; let keyD0 = getD0(_yt_player); if (!keyD0) return; const g = _yt_player let k = keyD0 const gk = g[k]; if (typeof gk !== 'function') return; const gkp = gk.prototype; gkp.playVideo48 = gkp.playVideo; gkp.playVideo = function(a) { let r = this.playVideo48(a); // console.log('gkpD0 playVideo',r, a) return r; } gkp.getVisibilityState48 = gkp.getVisibilityState; gkp.getVisibilityState = function(a, b, c, d, e, f, h, l) { let r = this.getVisibilityState48(a, b, c, d, e, f, h, l); // console.log('gkpD0 getVisibilityState',r, a,b,c,d,e,f,h,l) r = 0; return r; } gkp.getVideoData48 = gkp.getVideoData; gkp.getVideoData = function() { let r = this.getVideoData48(); // console.log('gkpD0 getVideoData',r) return r; } gkp.seekTo48 = gkp.seekTo; gkp.seekTo = function(a, b, c, d, e) { let r = this.seekTo48(a, b, c, d, e); // console.log('gkpD0 seekTo',r, a,b,c,d,e) return r; } gkp.pauseVideo48 = gkp.pauseVideo; gkp.pauseVideo = function(a, b) { let r = this.pauseVideo48(a, b); // console.log('gkpD0 pauseVideo',r, a,b); return r; } gkp.stopVideo48 = gkp.stopVideo; gkp.stopVideo = function(a) { let r = this.stopVideo48(a); // console.log('gkpD0 stopVideo',r,a) return r; } gkp.getPresentingPlayerType48 = gkp.getPresentingPlayerType; gkp.getPresentingPlayerType = function(a) { let r = this.getPresentingPlayerType48(a); // console.log('gkpD0 getPresentingPlayerType',r,a) return r; } gkp.getCurrentTime48 = gkp.getCurrentTime; gkp.getCurrentTime = function(a, b, c) { let r = this.getCurrentTime48(a, b, c); // console.log('gkpD0 getCurrentTime',r, a,b,c) return r; } gkp.cancelPlayback48 = gkp.cancelPlayback; gkp.cancelPlayback = function(a, b) { let r = this.cancelPlayback48(a, b); // console.log('gkpD0 cancelPlayback',r, a,b); return r; } })(); */ /** * * g.k.mL = function(a) { var b = a.target.Gf(); if (this.mediaElement && this.mediaElement.Gf() && this.mediaElement.Gf() === b) { ehb(this, a.type); switch (a.type) { case "error": var c = yFa(this.mediaElement) || "" , d = this.mediaElement.xf(); if (c === "capability.changed") { this.L("html5_restart_on_capability_change") ? (this.ma("capchg", { msg: d }), F_(this, !0)) : u0(this); return } if (this.mediaElement.hasError() && (Ndb(this.al, c, { msg: d }) || g.zS(this.videoData) && this.wb && this.wb.handleError(c))) return; if (this.isBackground() && this.mediaElement.fh() === 4) { this.So(); x0(this, "unplayable"); return } break; case "durationchange": c = this.mediaElement.getDuration(); isFinite(c) && (!this.Qa || c > 0) && c !== 1 && this.Hl(c); break; case "ratechange": this.ya && this.ya.setPlaybackRate(this.mediaElement.getPlaybackRate()); xfb(this.Ch); this.wc().onPlaybackRateChange(this.getPlaybackRate()); break; case "loadedmetadata": ghb(this); this.publish("onLoadedMetadata"); W5a(this); c = this.bf(); this.videoData.SB && (this.videoData.SB = c); break; case "loadstart": W5a(this); break; case "progress": case "suspend": this.Uc(); this.publish("onLoadProgress", this, this.Sw()); break; case "playing": this.Rb.uv("plev"); this.bT && !k0(this) && (this.bT = !1, this.isAtLiveHead() || (this.logger.debug("seek to infinity on PLAYING"), this.seekTo(Infinity, { kd: "videoplayer_onPlaying" }))); break; case "timeupdate": c = this.mediaElement && !this.mediaElement.getCurrentTime(); d = this.mediaElement && this.mediaElement.Tk() === 0; if (c && (!this.VK || d)) return; this.VK = this.VK || !!this.mediaElement.getCurrentTime(); Vgb(this); this.Uc(); if (!this.mediaElement || this.mediaElement.Gf() !== b) return; this.publish("onVideoProgress", this, this.getCurrentTime()); break; case "waiting": if (this.mediaElement.Vw().length > 0 && this.mediaElement.Eh().length === 0 && this.mediaElement.getCurrentTime() > 0 && this.mediaElement.getCurrentTime() < 5 && this.ya) return; this.L("html5_ignore_unexpected_waiting_cfl") && (this.mediaElement.isPaused() || this.mediaElement.Tk() > 2 || !this.mediaElement.isSeeking() && aK(this.mediaElement.Eh(), this.mediaElement.getCurrentTime())) && (c = this.mediaElement.uc(), c.bh = sK(this.mediaElement).toFixed(3), this.ma("uwe", c)); g.zS(this.videoData) && this.wb && n7a(this.wb, this.mediaElement.getCurrentTime()); break; case "resize": ghb(this); this.videoData.B && this.videoData.B.video.quality === "auto" && this.publish("internalvideoformatchange", this.videoData, !1); break; case "pause": if (this.TW && g.pF(this.playerState, 8) && !g.pF(this.playerState, 1024) && this.getCurrentTime() === 0 && g.VB) { x0(this, "safari_autoplay_disabled"); return } } if (this.mediaElement && this.mediaElement.Gf() === b) { dgb(this.Tc, a, this.wb || void 0); this.publish("videoelementevent", a); b = this.playerState; d = this.bE; var e = this.mediaElement; c = this.videoData.clientPlaybackNonce; var f = g.zS(this.videoData) && this.wb ? jY(this.wb) : void 0; if (!g.pF(b, 128)) { var h = b.state; e = e ? e : a.target; var l = e.getCurrentTime(); if (!g.pF(b, 64) || a.type !== "ended" && a.type !== "pause") { f = f || e.getDuration(); f = e.isEnded() || l > 1 && Math.abs(l - f) < 1.1; var m = a.type === "pause" && e.isEnded(); l = a.type === "ended" || a.type === "waiting" || a.type === "timeupdate" && !g.pF(b, 4) && !a0(d, l); if (m || f && l) e.KJ() > 0 && e.Gf() && (h = 14); else switch (a.type) { case "error": yFa(e) && (h |= 128); break; case "pause": g.pF(b, 256) ? (h ^= 256) || (h = 64) : g.pF(b, 32) || g.pF(b, 2) || g.pF(b, 4) || (h = 4, g.pF(b, 1) && g.pF(b, 8) && (h |= 1)); break; case "playing": l = h; h = (h | 8) & -1093; l & 4 ? (h |= 1, uK(d, e)) : a0(d, e.getCurrentTime()) && (h &= -2); g.pF(b, 1) && uK(d, e) && (h |= 1); break; case "seeking": h |= 16; g.pF(b, 8) && (h |= 1); h &= -3; break; case "seeked": h &= -17; uK(d, e); break; case "waiting": g.pF(b, 2) || (h |= 1); uK(d, e); break; case "timeupdate": l = g.pF(b, 16), f = g.pF(b, 4), (g.pF(b, 8) || l) && !f && a0(d, e.getCurrentTime()) && (h = 8), uK(d, e) && (h |= 1) } } d = h; h = null; d & 128 && (h = a.target, e = yFa(h), l = 1, e ? (e === "capability.changed" && (l = 2), f = "GENERIC_WITHOUT_LINK", m = h.uc(), m.mediaElem = "1", /AUDIO_RENDERER/.test(h.xf()) && (f = "HTML5_AUDIO_RENDERER_ERROR"), h = { errorCode: e, errorMessage: g.JV[f] || "", bP: f, KL: yJ(m), rJ: l, cpn: b.Pg ? b.Pg.cpn : "" }) : h = null, h && (h.cpn = c)); b = vK(b, d, h) } !g.pF(this.playerState, 1) && g.pF(b, 1) && dhb(this, "evt" + a.type); this.Ic(b) } } } ; * * */ (async () => { // rAf scheduling const _yt_player = await _yt_player_observable.obtain(); if (!_yt_player || typeof _yt_player !== 'object') return; let keys0 = gets0(_yt_player); if (!keys0) return; const g = _yt_player let k = keys0 const gk = g[k]; if (typeof gk !== 'function') return; const gkp = gk.prototype; // gkp.isBackground48 = gkp.isBackground; // gkp.isBackground = function() { // if(!this?.visibility?.isBackground88){ // this.visibility.isBackground88 = 1; // this.visibility.isBackground = function(){ // return false; // } // } // // console.log('gkps0', 'isBackground', this.visibility) // // return false; // // if(!this.mediaElement || !(this.mediaElement.readyState>=4)){ // // return false; // // } // // console.log(1882,) // return this.isBackground48(); // } gkp.publish48 = gkp.publish; gkp.publish33 = async function(a,b){ const player_ = kRef(globalPlayer); let publishStatus = 0; const media = this.mediaElement; if(a==='internalaudioformatchange' && typeof (b.author||0) === 'string' && media && player_){ await player_.clearVideo(); // avoid error in live streaming await player_.clearQueue(); // avoid error in live streaming await refreshAllStaleEntitiesForNonReadyAudio(); // await player_.cancelPlayback(); publishStatus = media.__publishStatus17__ = 100; } const domMedia = media ? Object.values(media).filter(e => e instanceof HTMLMediaElement) : []; if (this.mediaElement && a !== 'internalvideoformatchange' && player_ && domMedia.length === 1) { const audio = domMedia[0]; const refreshAllStaleEntitiesForNonReadyAudio = async () => { try { if (audio.readyState == 0 && audio.isConnected === true) await player_.refreshAllStaleEntities(); } catch (e) { } }; // const triggerPlaying = async () => { // await player_.cancelPlayback(); // this.pauseVideo(); // this.playVideo(); // await player_.pauseVideo(); // await player_.playVideo(); // }; const seekToLiveHeadForLiveStream = async () => { try { audio.isConnected === true && await player_.seekToLiveHead(); if (audio.isConnected === true && (await player_.isAtLiveHead()) === true) { audio.isConnected === true && await player_.seekToStreamTime(); return true; } } catch (e) { console.log('error_F7', e); } }; if(a.includes('error') ){ if(!media.__publishStatus17__ || media.__publishStatus17__ < 200){ await player_.clearVideo(); // avoid error in live streaming await player_.clearQueue(); // avoid error in live streaming await refreshAllStaleEntitiesForNonReadyAudio(); // await player_.cancelPlayback(); } }else{ media.__publishStatus17__ = media.__publishStatus17__ || 100; if (media.__publishStatus17__ === 100) await refreshAllStaleEntitiesForNonReadyAudio(); if (media.__publishStatus17__ === 100 && audio.duration > 0 && player_.getPlayerState() === 3) { media.__publishStatus17__ = 200 // await refreshAllStaleEntitiesForNonReadyAudio(); await player_.cancelPlayback(); await this.pauseVideo(); // this.playVideo(); // await player_.pauseVideo(); await player_.playVideo(); await seekToLiveHeadForLiveStream(); // fixLiveAudioFn(domMedia0, player_, player_.getPlayerState()) // skipPause = true; // skipVisibility = true; // player_.cancelPlayback(); // player_.pauseVideo(); // player_.playVideo(); // skipPause = false; // skipVisibility = false; } if (a === 'onLoadedMetadata' && media.__publishStatus17__ === 200) media.__publishStatus17__ = 201; if (a === 'videoelementevent' && b.type === 'loadedmetadata' && media.__publishStatus17__ === 201) media.__publishStatus17__ = 202; if (a === 'videoelementevent' && b.type === 'progress' && media.__publishStatus17__ === 202) { media.__publishStatus17__ = 203; window.debug_mfk = this; window.debug_mfp = player_; // (async ()=>{ // await timelineResolve(); // const domMedia = Object.values(this.mediaElement).filter(e=>e instanceof HTMLMediaElement); // if(domMedia.length === 1){ // const domMedia0 = domMedia[0] // if(domMedia0.duration >0 && domMedia0.readyState >= 4){ // await timelineResolve(); // console.log(939, domMedia0, domMedia0.paused, domMedia0.duration, domMedia0.readyState) // this.pauseVideo(); // await timelineResolve(); // this.playVideo(); // } // // this.mediaElement.pause(); // // this.mediaElement.play(); // } // })(); } if (media.__publishStatus17__ === 203 && audio && audio.readyState === 1) { media.__publishStatus17__ = 204; // await timelineResolve(); // await player_.cancelPlayback(); await this.pauseVideo(); // this.playVideo(); // await timelineResolve(); // await player_.pauseVideo(); await player_.playVideo(); // await timelineResolve(); await seekToLiveHeadForLiveStream(); } if (media.__publishStatus17__ < 300 && media.__publishStatus17__ >= 200 && a === 'videoelementevent' && b.type==='timeupdate' && !audio.paused && audio.readyState >= 4 && audio.duration > 0) { media.__publishStatus17__ = 300; if(!player_.isAtLiveHead()) await seekToLiveHeadForLiveStream(); } } publishStatus = media.__publishStatus17__; if (debugFlg001) console.log('gkps0 publish | ' + publishStatus, a, printObject(b)) } } gkp.publish = function(a,b){ this.publish33(a,b); return this.publish48.apply(this, arguments); } // console.log(23488) })(); })(); } const getVideoIdByURL = () => { // It's almost certainly going to stay at 11 characters. The individual characters come from a set of 64 possibilities (A-Za-z0-9_-). // base64 form; 26+26+10+2; 64^len // Math.pow(64,11) = 73786976294838210000 const url = new URL(location.href); let m; if (m = /^\/watch\?v=([A-Za-z0-9_-]+)/.exec(`${url.pathname}?v=${url.searchParams.get('v')}`)) return `${m[1]}`; if (m = /^\/live\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`; if (m = /^\/embed\/live_stream\?channel=([A-Za-z0-9_-]+)/.exec(`${url.pathname}?channel=${url.searchParams.get('channel')}`)) return `L:${m[1]}`; if (m = /^\/embed\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`; if (m = /^\/channel\/([A-Za-z0-9_-]+)\/live\b/.exec(url.pathname)) return `L:${m[1]}`; if (url.hostname === 'youtu.be' && (m = /\/([A-Za-z0-9_-]+)/.exec(url.pathname))) return `${m[1]}`; return ''; }; const getVideoIdByElement = ()=>{ const videoIdElements = [...document.querySelectorAll('[video-id]')].filter(v => !v.closest('[hidden]')); const videoId = videoIdElements.length > 0 ? videoIdElements[0].getAttribute('video-id') : null; return videoId || ''; }; const getEnableValue = async ()=>{ const videoId = getVideoIdByURL() || getVideoIdByElement(); const siteVal = videoId ? await GM.getValue(`isEnable_aWsjF_${videoId}`, null) : null; return (siteVal !== null) ? siteVal : await GM.getValue("isEnable_aWsjF", true); }; const setEnableVal = async (val)=>{ const videoId = getVideoIdByURL() || getVideoIdByElement(); if (videoId) { try { const cv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null); if (typeof cv === typeof val) await GM.setValue(`isEnable_aWsjF_${videoId}`, val); } catch (e) { } } await GM.setValue("isEnable_aWsjF", val); } const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? await getEnableValue() : null; if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError"); if (isEnable) { const element = document.createElement('button'); element.setAttribute('onclick', createHTML(`(${pageInjectionCode})()`)); element.click(); } GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () { await setEnableVal(!isEnable); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); }); let messageCount = 0; let busy = false; window.addEventListener('message', (evt) => { const v = ((evt || 0).data || 0).ZECxh; if (typeof v === 'boolean') { if (messageCount > 1e9) messageCount = 9; const t = ++messageCount; if (v && isEnable) { requestAnimationFrame(async () => { if (t !== messageCount) return; if (busy) return; busy = true; if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) { await setEnableVal(!isEnable); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); } busy = false; }); } } }); const pLoad = new Promise(resolve => { if (document.readyState !== 'loading') { resolve(); } else { window.addEventListener("DOMContentLoaded", resolve, false); } }); function contextmenuInfoItemAppearedFn(target) { const btn = target.closest('.ytp-menuitem[role="menuitem"]'); if (!btn) return; if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return; document.documentElement.classList.add('with-audio-only-toggle-btn'); const newBtn = btn.cloneNode(true) newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`; newBtn.classList.add('audio-only-toggle-btn'); btn.parentNode.insertBefore(newBtn, btn.nextSibling); newBtn.addEventListener('click', async (evt) => { try { evt.stopPropagation(); evt.stopImmediatePropagation(); } catch (e) { } await setEnableVal(!isEnable); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); }); let t; let h = 0; t = btn.closest('.ytp-panel-menu[style*="height"]'); if (t) t.style.height = t.scrollHeight + 'px'; t = btn.closest('.ytp-panel[style*="height"]'); if (t) t.style.height = (h = t.scrollHeight) + 'px'; t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]'); if (t && h > 0) t.style.height = h + 'px'; } function mobileMenuItemAppearedFn(target) { const btn = target.closest('ytm-menu-item'); if (!btn) return; if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return; document.documentElement.classList.add('with-audio-only-toggle-btn'); const newBtn = btn.cloneNode(true); newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`; newBtn.classList.add('audio-only-toggle-btn'); btn.parentNode.insertBefore(newBtn, btn.nextSibling); newBtn.addEventListener('click', async (evt) => { try { evt.stopPropagation(); evt.stopImmediatePropagation(); } catch (e) { } await setEnableVal(!isEnable); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); }); } const lastEntry = (arr) => { return arr.length > 0 ? arr[arr.length - 1] : null; } function mobileMenuItemAppearedV2Fn(target) { const btn = target.closest('yt-list-item-view-model'); if (!(btn instanceof HTMLElement)) return; if (btn.parentNode.querySelector('yt-list-item-view-model.audio-only-toggle-btn')) return; const parentNode = btn.closest('player-settings-menu'); if(!parentNode) return; let qt = 1E9; let targetBtnO = lastEntry([...parentNode.getElementsByTagName(btn.nodeName)].filter(e => e.parentElement === btn.parentElement).map((elm) => { const count = elm.getElementsByTagName('*').length; if (count < qt) qt = count; return { elm: elm, count: count } }).filter((o) => o.count === qt)); const targetBtn = targetBtnO && targetBtnO.elm instanceof HTMLElement ? targetBtnO.elm : btn; const newBtn = targetBtn.cloneNode(true); if(newBtn instanceof HTMLElement){ document.documentElement.classList.add('with-audio-only-toggle-btn'); let newBtnContentElm = newBtn; let layerCN = 8; while (newBtnContentElm.childElementCount === 1 && layerCN--) { newBtnContentElm = newBtnContentElm.firstElementChild; } if (!(newBtnContentElm instanceof HTMLElement)) newBtnContentElm = newBtn; let t; if (t = lastEntry(newBtnContentElm.querySelectorAll('span[role="text"]'))) { newBtnContentElm = t; newBtnContentElm.classList.add('audio-only-toggle-btn-content2'); } else if (t = lastEntry(newBtnContentElm.querySelectorAll('[role="text"]'))) { newBtnContentElm = t; newBtnContentElm.classList.add('audio-only-toggle-btn-content2'); } else if (t = lastEntry(newBtnContentElm.querySelectorAll('span'))) { newBtnContentElm = t; newBtnContentElm.classList.add('audio-only-toggle-btn-content2'); } else if (t = lastEntry(newBtnContentElm.querySelector('.yt-core-attributed-string'))) { newBtnContentElm = t; newBtnContentElm.classList.add('audio-only-toggle-btn-content2'); } newBtnContentElm.textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`; newBtn.classList.add('audio-only-toggle-btn'); newBtnContentElm.classList.add('audio-only-toggle-btn-content'); btn.parentNode.insertBefore(newBtn, btn.nextSibling); newBtn.addEventListener('click', async (evt) => { try { evt.stopPropagation(); evt.stopImmediatePropagation(); } catch (e) { } await setEnableVal(!isEnable); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); }); const contentWrapper = newBtn.closest('#content-wrapper'); if (contentWrapper) { contentWrapper.style.height = 'unset'; contentWrapper.style.maxHeight = 'unset'; } } } pLoad.then(() => { document.addEventListener('animationstart', (evt) => { const animationName = evt.animationName; if (!animationName) return; if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target); if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target); if (animationName === 'mobileMenuItemAppearedV2') mobileMenuItemAppearedV2Fn(evt.target); }, true); const cssForEnabled = isEnable ? ` .html5-video-player { background-color: black; } [style*="--audio-only-thumbnail-image"]{ background-image: var(--audio-only-thumbnail-image); object-fit: contain; background-position: center; background-size: contain; background-repeat: no-repeat; } .html5-video-player.ended-mode [style*="--audio-only-thumbnail-image"]{ background-image: none; } .html5-video-player.ytp-ce-shown .html5-video-container { opacity: 0.5; transition: opacity 0.5s; } ytd-video-preview #media-container div#player-container, ytd-video-preview #media-container div#thumbnail-container{ transition: initial !important; transition-duration:0ms !important; transition-delay:0ms !important; } ytd-video-preview #media-container div#thumbnail-container{ /* pointer-events:none !important; */ opacity:0; /* z-index:-1; */ } ytd-video-preview #media-container div#player-container, ytd-video-preview #media-container div#inline-preview-player{ background-color:transparent !important; background-image:none !important; } #movie_player > .html5-video-container:not(:empty) { box-sizing: border-box; height: 100%; } #movie_player [style*="--audio-only-thumbnail-image"] ~ .ytp-cued-thumbnail-overlay > .ytp-cued-thumbnail-overlay-image[style*="background-image"] { opacity: 0; } #movie_player [style*="--audio-only-thumbnail-image"]::before { content: ''; display: block; position: absolute; left: 0; top: 0; bottom: 0; right: 0; /* background: transparent; */ /* We use multiple backgrounds: one gradient per side */ background: /* Left border gradient */ linear-gradient(to right, rgba(0,0,0,0.4), transparent) left center, /* Right border gradient */ linear-gradient(to left, rgba(0,0,0,0.4), transparent) right center, /* Top border gradient */ linear-gradient(to bottom, rgba(0,0,0,0.4), transparent) center top, /* Bottom border gradient */ linear-gradient(to top, rgba(0,0,0,0.4), transparent) center bottom; /* Prevents repetition of gradients */ background-repeat: no-repeat; /* Set the size of each gradient "border" */ background-size: 12% 100%, /* left border width and full height */ 12% 100%, /* right border width and full height */ 100% 12%, /* top border full width and small height */ 100% 12%; /* bottom border full width and small height */ /* Optional: a base background color inside the element */ /* background-color: #fff; */ /* background-color: var(--blinker-fmw83-bgc, transparent); */ opacity: var(--fmw83-opacity, 1); pointer-events: none !important; z-index:-1; } /* @keyframes blinker-fmw83 { 0%, 60%, 100% { opacity: 1; } 30% { opacity: 0.96; } } */ #movie_player.playing-mode [style*="--audio-only-thumbnail-image"]{ /* animation: blinker-fmw83 1.74s linear infinite; */ --fmw83-opacity: 0.6; } `: ""; const style = document.createElement('style'); style.id = 'fm9v0'; style.textContent = ` ${cssForEnabled} @keyframes mobileMenuItemAppeared { 0% { background-position-x: 3px; } 100% { background-position-x: 4px; } } @keyframes mobileMenuItemAppearedV2 { 0% { background-position-x: 3px; } 100% { background-position-x: 4px; } } ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type { animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards; } player-settings-menu > yt-list-item-view-model:last-of-type { animation: mobileMenuItemAppearedV2 1ms linear 0s 1 normal forwards; } player-settings-menu .audio-only-toggle-btn-content { padding: 14px 24px; box-sizing: border-box; font-size: 130%; } player-settings-menu .audio-only-toggle-btn-content2 { padding: 0; box-sizing: border-box; font-size: inherit; } @keyframes contextmenuInfoItemAppeared { 0% { background-position-x: 3px; } 100% { background-position-x: 4px; } } .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{ animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards; } #confirmDialog794 { z-index:999999 !important; display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 1; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ } #confirmDialog794 .confirm-box { position:relative; color: black; z-index:999999 !important; background-color: #fefefe; margin: 15% auto; /* 15% from the top and centered */ padding: 20px; border: 1px solid #888; width: 30%; /* Could be more or less, depending on screen size */ box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); } #confirmDialog794 .confirm-buttons { text-align: right; } #confirmDialog794 button { margin-left: 10px; } ` document.head.appendChild(style); }); const pNavigateFinished = new Promise(resolve => { document.addEventListener('yt-navigate-finish', resolve, true); }); pNavigateFinished.then(() => { const inputs = document.querySelectorAll('#masthead input[type="text"][name]'); let lastInputTextValue = null; let busy = false; let disableMonitoring = false; const setGV = async (val)=>{ const videoId = getVideoIdByURL() || getVideoIdByElement(); if (videoId) { const cgv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null); if (cgv !== val || isEnable !== val) { disableMonitoring = true; await GM.setValue(`isEnable_aWsjF_${videoId}`, val); await GM.setValue('lastCheck_bWsm5', Date.now()); document.documentElement.setAttribute('forceRefresh032', ''); location.reload(); } } } const checkTextChangeF = async (evt) => { busy = false; const inputElem = (evt || 0).target; if (inputElem instanceof HTMLInputElement && !disableMonitoring) { const cv = inputElem.value; if (cv === lastInputTextValue) return; lastInputTextValue = cv; if (cv === 'vvv') { await setGV(false); } else if (cv === 'aaa') { await setGV(true); } } } const checkTextChange = (evt) => { if (busy) return; busy = true; Promise.resolve(evt).then(checkTextChangeF) }; for (const input of inputs) { input.addEventListener('input', checkTextChange, false); input.addEventListener('keydown', checkTextChange, false); input.addEventListener('keyup', checkTextChange, false); input.addEventListener('keypress', checkTextChange, false); input.addEventListener('change', checkTextChange, false); } }); const autoCleanUpKey = async () => { const lastCheck = await GM.getValue('lastCheck_bWsm5', null) || 0; if (Date.now() - lastCheck < 16000) return; // 16s GM.setValue('lastCheck_bWsm5', Date.now()); pLoad.then(async () => { const rArr = []; const arr = await GM.listValues(); const cv = await GM.getValue("isEnable_aWsjF", null); const fn = async (entry) => { try { if (typeof entry === 'string' && entry.length > 15 && entry.startsWith('isEnable_aWsjF_')) { const res = await GM.getValue(entry, null); if (typeof res === 'boolean' && res === cv) { await GM.deleteValue(entry); rArr.push(entry); } } } catch (e) { console.warn(e); } } arr.length > 1 && (await Promise.all(arr.map(fn))); rArr.length > 0 && console.log('[YouTube Audio Only] autoCleanUpKey', rArr); }); }; autoCleanUpKey(); })();