YouTube: Audio Only

No Video Streaming

当前为 2024-12-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube: Audio Only
  3. // @description No Video Streaming
  4. // @namespace UserScript
  5. // @version 1.9.1
  6. // @author CY Fung
  7. // @match https://www.youtube.com/*
  8. // @match https://www.youtube.com/embed/*
  9. // @match https://www.youtube-nocookie.com/embed/*
  10. // @match https://m.youtube.com/*
  11. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  12. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/YouTube-Audio-Only.png
  13. // @grant GM_registerMenuCommand
  14. // @grant GM.setValue
  15. // @grant GM.getValue
  16. // @grant GM.listValues
  17. // @grant GM.deleteValue
  18. // @run-at document-start
  19. // @license MIT
  20. // @compatible chrome
  21. // @compatible firefox
  22. // @compatible opera
  23. // @compatible edge
  24. // @compatible safari
  25. // @allFrames true
  26. //
  27. // ==/UserScript==
  28.  
  29. (async function () {
  30. 'use strict';
  31.  
  32. !window.TTP && (() => {
  33. // credit to Benjamin Philipp
  34. // original source: https://greasyfork.org/en/scripts/433051-trusted-types-helper
  35. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  36. 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
  37. const prefix = `TTP`;
  38. var passThroughFunc = function (string, sink) {
  39. return string; // Anything passing through this function will be returned without change
  40. }
  41. var TTPName = "passthrough";
  42. 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
  43. var needsTrustedHTML = false;
  44. function doit() {
  45. try {
  46. if (typeof window.isSecureContext !== 'undefined' && window.isSecureContext) {
  47. if (window.trustedTypes && window.trustedTypes.createPolicy) {
  48. needsTrustedHTML = true;
  49. if (trustedTypes.defaultPolicy) {
  50. log("TT Default Policy exists");
  51. if (overwrite_default)
  52. TTP = window.trustedTypes.createPolicy("default", TTP);
  53. else
  54. TTP = window.trustedTypes.createPolicy(TTPName, TTP); // Is the default policy permissive enough? If it already exists, best not to overwrite it
  55. TTP_default = trustedTypes.defaultPolicy;
  56. log("Created custom passthrough policy, in case the default policy is too restrictive: Use Policy '" + TTPName + "' in var 'TTP':", TTP);
  57. }
  58. else {
  59. TTP_default = TTP = window.trustedTypes.createPolicy("default", TTP);
  60. }
  61. log("Trusted-Type Policies: TTP:", TTP, "TTP_default:", TTP_default);
  62. }
  63. }
  64. } catch (e) {
  65. log(e);
  66. }
  67. }
  68. function log(...args) {
  69. if ("undefined" != typeof (prefix) && !!prefix)
  70. args = [prefix + ":", ...args];
  71. if ("undefined" != typeof (debugging) && !!debugging)
  72. args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")];
  73. console.log(...args);
  74. }
  75. doit();
  76. // --------------------------------------------------- Trusted Types Helper ---------------------------------------------------
  77. window.TTP = TTP;
  78. })();
  79. function createHTML(s) {
  80. if (typeof TTP !== 'undefined' && typeof TTP.createHTML === 'function') return TTP.createHTML(s);
  81. return s;
  82. }
  83. let trustHTMLErr = null;
  84. try {
  85. document.createElement('div').innerHTML = createHTML('1');
  86. } catch (e) {
  87. trustHTMLErr = e;
  88. }
  89. if (trustHTMLErr) {
  90. console.log(`trustHTMLErr`, trustHTMLErr);
  91. trustHTMLErr(); // exit userscript
  92. }
  93.  
  94. /** @type {globalThis.PromiseConstructor} */
  95. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  96.  
  97. if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError");
  98.  
  99. async function confirm(message) {
  100. // Create the HTML for the dialog
  101.  
  102. if (!document.body) return;
  103.  
  104. let dialog = document.getElementById('confirmDialog794');
  105. if (!dialog) {
  106.  
  107. const dialogHTML = `
  108. <div id="confirmDialog794" class="dialog-style" style="display: block;">
  109. <div class="confirm-box">
  110. <p>${message}</p>
  111. <div class="confirm-buttons">
  112. <button id="confirmBtn">Confirm</button>
  113. <button id="cancelBtn">Cancel</button>
  114. </div>
  115. </div>
  116. </div>
  117. `;
  118.  
  119. // Append the dialog to the document body
  120. document.body.insertAdjacentHTML('beforeend', createHTML(dialogHTML));
  121. dialog = document.getElementById('confirmDialog794');
  122.  
  123. }
  124.  
  125. // Return a promise that resolves or rejects based on the user's choice
  126. return new Promise((resolve) => {
  127. document.getElementById('confirmBtn').onclick = () => {
  128. resolve(true);
  129. cleanup();
  130. };
  131.  
  132. document.getElementById('cancelBtn').onclick = () => {
  133. resolve(false);
  134. cleanup();
  135. };
  136.  
  137. function cleanup() {
  138. dialog && dialog.remove();
  139. dialog = null;
  140. }
  141. });
  142. }
  143.  
  144.  
  145.  
  146. if (location.pathname === '/live_chat' || location.pathname === 'live_chat_replay') return;
  147.  
  148. const kEventListener = (evt) => {
  149. if (document.documentElement.hasAttribute('forceRefresh032')) {
  150. evt.stopImmediatePropagation();
  151. evt.stopPropagation();
  152. }
  153. }
  154. window.addEventListener('beforeunload', kEventListener, false);
  155.  
  156. const pageInjectionCode = function () {
  157.  
  158. let debugFlg001 = false;
  159. // let debugFlg002 = false;
  160. let globalPlayer = null;
  161. const SHOW_VIDEO_STATIC_IMAGE = true;
  162. const PATCH_MEDIA_PUBLISH = true;
  163.  
  164. if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError");
  165.  
  166. const URL = window.URL || new Function('return URL')();
  167. const createObjectURL = URL.createObjectURL.bind(URL);
  168.  
  169. /** @type {globalThis.PromiseConstructor} */
  170. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  171.  
  172. const PromiseExternal = ((resolve_, reject_) => {
  173. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  174. return class PromiseExternal extends Promise {
  175. constructor(cb = h) {
  176. super(cb);
  177. if (cb === h) {
  178. /** @type {(value: any) => void} */
  179. this.resolve = resolve_;
  180. /** @type {(reason?: any) => void} */
  181. this.reject = reject_;
  182. }
  183. }
  184. };
  185. })();
  186.  
  187. /* globals WeakRef:false */
  188.  
  189. /** @type {(o: Object | null) => WeakRef | null} */
  190. const mWeakRef = typeof WeakRef === 'function' ? (o => o ? new WeakRef(o) : null) : (o => o || null);
  191.  
  192. /** @type {(wr: Object | null) => Object | null} */
  193. const kRef = (wr => (wr && wr.deref) ? wr.deref() : wr);
  194.  
  195. /*
  196.  
  197. g.k.playVideo = function(a) {
  198. this.logger.debug(function() {
  199. return "play video, player type " + a
  200. });
  201. var b = g.rT(this, a);
  202. b && (this.appState === 2 ? (g.BR(this.X) && $U(this.Rb),
  203. N0(this)) : g.pF(b.getPlayerState(), 2) ? (b = 36,
  204. this.getVideoData().nk() && (b = 37),
  205. this.seekTo(0, void 0, void 0, void 0, b)) : b.playVideo())
  206. }
  207.  
  208. g.k.getPresentingPlayerType = function(a) {
  209. if (this.appState === 1)
  210. return 1;
  211. if (J0(this))
  212. return 3;
  213. var b;
  214. if (a && ((b = this.ye) == null ? 0 : b.vl(this.getCurrentTime())))
  215. return 2;
  216. var c;
  217. return g.zS(this.getVideoData()) && ((c = this.wb) == null ? 0 : c.vl()) ? 2 : g.rT(this).getPlayerType()
  218. }
  219.  
  220. g.k.rS = function() {
  221. var a = this.app.getPresentingPlayerType();
  222. if (a === 2 && !this.app.Jf()) {
  223. var b = zV(this.app.zb());
  224. if (!Dkb(b) || Ekb(b))
  225. return
  226. }
  227. 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)
  228. }
  229. */
  230.  
  231. // const onDurationAvailable = async function(player_, media){
  232. // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 1) {
  233. // skipPause = true;
  234. // skipVisibility = true;
  235. // debugFlg002 && console.log(1991, player_.getPresentingPlayerType())
  236. // await player_.cancelPlayback();
  237. // debugFlg002 && console.log(1992, player_.getPresentingPlayerType())
  238. // await player_.pauseVideo();
  239. // debugFlg002 && console.log(1993, player_.getPresentingPlayerType())
  240. // // window.m33e = 1;
  241. // window.m34e = player_;
  242. // // await player_.clearQueue();
  243. // await player_.playVideo();
  244. // skipVisibility = false;
  245. // skipPause = false;
  246.  
  247. // debugFlg002 && console.log('HTMLMediaElement A2', [media.readyState, media.paused, media.networkState]);
  248. // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 4) {
  249. // media.__canPlayPromise__.resolve();
  250. // media.__canPlayPromise__ = null;
  251. // }
  252. // }
  253. // }
  254.  
  255. // let skipPause = false;
  256. // let skipVisibility = false;
  257. // const durationchangeListener = async function (evt) {
  258. // const media = evt ? evt.target : null;
  259. // if (media instanceof HTMLMediaElement && media.__canPlayPromise__ && media.duration > 0 && media.networkState >= 2 && media.readyState >= 1) {
  260. // if (media.readyState < 4) {
  261. // debugFlg002 && console.log('HTMLMediaElement A1', [media.readyState, media.paused, media.networkState])
  262. // const player_ = kRef(globalPlayer);
  263. // if (player_) {
  264. // onDurationAvailable(player_, media);
  265. // } else {
  266. // console.error("HTMLMediaElement", "player_ is not found when HTMLMediaElement duration change");
  267. // }
  268. // } else {
  269. // debugFlg002 && console.log('HTMLMediaElement B', [media.readyState, media.paused, media.networkState])
  270. // media.__canPlayPromise__.resolve();
  271. // media.__canPlayPromise__ = null;
  272. // }
  273. // }
  274. // }
  275.  
  276. // const canplayListener = function (evt) {
  277. // const media = evt ? evt.target : null;
  278. // if (media && media.__canPlayPromise__) {
  279. // debugFlg002 && console.log('HTMLMediaElement canplay', [media.readyState, media.paused, media.networkState]);
  280. // media.__canPlayPromise__.resolve();
  281. // media.__canPlayPromise__ = null;
  282. // }
  283. // debugFlg002 && console.log('HTMLMediaElement canplay')
  284. // }
  285.  
  286. // let x6CGdPr = null;
  287. // window.addEventListener('message', (evt)=>{
  288. // if((evt||0).data === 'x6CGd' && x6CGdPr!==null) x6CGdPr.resolve();
  289. // });
  290. // const timelineResolve = async () => {
  291. // if (x6CGdPr !== null) {
  292. // await x6CGdPr.then();
  293. // return;
  294. // }
  295. // x6CGdPr = new PromiseExternal();
  296. // window.postMessage('x6CGd');
  297. // await x6CGdPr.then();
  298. // x6CGdPr = null;
  299. // }
  300.  
  301. // let playWId = 0;
  302.  
  303. // const mediaPlay = HTMLMediaElement.prototype.play
  304. // HTMLMediaElement.prototype.play = function () {
  305. // debugFlg002 && console.log('HTMLMediaElement play')
  306. // if (playWId > 1e9) playWId = 9;
  307. // const tid = ++playWId;
  308. // if (!this.paused) {
  309. // return mediaPlay.apply(this, arguments);
  310. // }
  311. // if (this.readyState >= 4) return mediaPlay.apply(this, arguments);
  312. // try {
  313. // if (!this.__canPlayPromise__ && this.closest('#player')) {
  314. // this.__canPlayPromise__ = new PromiseExternal();
  315. // const player_ = kRef(globalPlayer);
  316. // debugFlg002 && console.log('HTMLMediaElement play x', this.duration, player_)
  317. // if (!(this.duration > 0)) {
  318. // this.removeEventListener('durationchange', durationchangeListener);
  319. // this.addEventListener('durationchange', durationchangeListener);
  320. // this.removeEventListener('canplay', canplayListener);
  321. // this.addEventListener('canplay', canplayListener);
  322. // } else if (player_) {
  323. // this.removeEventListener('canplay', canplayListener);
  324. // this.addEventListener('canplay', canplayListener);
  325. // onDurationAvailable(player_, this);
  326. // } else {
  327. // console.error("HTMLMediaElement", "player_ is not found when HTMLMediaElement plays");
  328. // }
  329.  
  330. // //---------------
  331.  
  332.  
  333. // // this.addEventListener('canplaythrough', function(){
  334. // // console.log('HTMLMediaElement canplaythrough')
  335. // // });
  336. // // this.addEventListener('loadeddata', function(){
  337. // // console.log('HTMLMediaElement loadeddata')
  338. // // });
  339. // // this.addEventListener('loadedmetadata', function(){
  340. // // console.log('HTMLMediaElement loadedmetadata')
  341. // // });
  342.  
  343. // //---------------
  344.  
  345. // // this.addEventListener('abort', function(){
  346. // // console.log('HTMLMediaElement abort')
  347. // // });
  348. // // this.addEventListener('emptied', function(){
  349. // // console.log('HTMLMediaElement emptied')
  350. // // });
  351. // // this.addEventListener('error', function(){
  352. // // console.log('HTMLMediaElement error')
  353. // // });
  354. // // this.addEventListener('ended', function(){
  355. // // console.log('HTMLMediaElement ended')
  356. // // });
  357. // // this.addEventListener('loadstart', function(){
  358. // // console.log('HTMLMediaElement loadstart')
  359. // // });
  360. // }
  361.  
  362. // } catch (e) {
  363. // console.log('HTMLMediaElement.prototype.play error');
  364. // console.error(e);
  365. // this.__canPlayPromise__ = Promise.resolve();
  366. // }
  367. // const promise = this.__canPlayPromise__;
  368. // return (async () => {
  369. // await promise.then();
  370. // if (tid !== playWId) return;
  371. // return await mediaPlay.apply(this, arguments);
  372. // })();
  373. // }
  374. // const mediaPause = HTMLMediaElement.prototype.pause
  375. // HTMLMediaElement.prototype.pause = function () {
  376. // if (skipPause) return;
  377. // debugFlg002 && console.log('HTMLMediaElement pause')
  378. // if (playWId > 1e9) playWId = 9;
  379. // const tid = ++playWId;
  380. // const promise = this.__canPlayPromise__;
  381. // if (promise) {
  382. // promise.resolve();
  383. // this.__canPlayPromise__ = null;
  384. // }
  385. // return mediaPause.apply(this, arguments);
  386. // }
  387.  
  388.  
  389.  
  390. const createPipeline = () => {
  391. let pipelineMutex = Promise.resolve();
  392. const pipelineExecution = fn => {
  393. return new Promise((resolve, reject) => {
  394. pipelineMutex = pipelineMutex.then(async () => {
  395. let res;
  396. try {
  397. res = await fn();
  398. } catch (e) {
  399. console.log('error_F1', e);
  400. reject(e);
  401. }
  402. resolve(res);
  403. }).catch(console.warn);
  404. });
  405. };
  406. return pipelineExecution;
  407. }
  408.  
  409. const observablePromise = (proc, timeoutPromise) => {
  410. let promise = null;
  411. return {
  412. obtain() {
  413. if (!promise) {
  414. promise = new Promise(resolve => {
  415. let mo = null;
  416. const f = () => {
  417. let t = proc();
  418. if (t) {
  419. mo.disconnect();
  420. mo.takeRecords();
  421. mo = null;
  422. resolve(t);
  423. }
  424. }
  425. mo = new MutationObserver(f);
  426. mo.observe(document, { subtree: true, childList: true })
  427. f();
  428. timeoutPromise && timeoutPromise.then(() => {
  429. resolve(null)
  430. });
  431. });
  432. }
  433. return promise
  434. }
  435. }
  436. }
  437.  
  438.  
  439. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  440.  
  441. const prototypeInherit = (d, b) => {
  442. const m = Object.getOwnPropertyDescriptors(b);
  443. for (const p in m) {
  444. if (!Object.getOwnPropertyDescriptor(d, p)) {
  445. Object.defineProperty(d, p, m[p]);
  446. }
  447. }
  448. };
  449.  
  450. let setTimeout_ = setTimeout;
  451. let clearTimeout_ = clearTimeout;
  452.  
  453. const delayPn = delay => new Promise((fn => setTimeout_(fn, delay)));
  454.  
  455. const isWatchPageURL = (url) => {
  456. url = url || location;
  457. return location.pathname === '/watch' || location.pathname.startsWith('/live/')
  458. };
  459.  
  460. const mockEvent = (o, elem) => {
  461. o = o || {};
  462. elem = elem || null;
  463. return {
  464. preventDefault: () => { },
  465. stopPropagation: () => { },
  466. stopImmediatePropagation: () => { },
  467. returnValue: true,
  468. target: elem,
  469. srcElement: elem,
  470. defaultPrevented: false,
  471. cancelable: true,
  472. timeStamp: performance.now(),
  473. ...o
  474. }
  475. };
  476.  
  477.  
  478. const generalRegister = (prop, symbol, checker, pg) => {
  479. const objSet = new Set();
  480. let done = false;
  481. const f = (o) => {
  482. const ct = o.constructor;
  483. const proto = ct.prototype;
  484. if (!done && proto && ct !== Function && ct !== Object && checker(proto)) {
  485. done = true;
  486. delete Object.prototype[prop];
  487. objSet.delete(proto);
  488. objSet.delete(o);
  489. for (const obj of objSet) {
  490. obj[prop] = obj[symbol];
  491. delete obj[symbol];
  492. }
  493. objSet.clear();
  494. Object.defineProperty(proto, prop, pg);
  495. return proto;
  496. }
  497. return false;
  498. };
  499. Object.defineProperty(Object.prototype, prop, {
  500. get() {
  501. const p = f(this);
  502. if (p) {
  503. return p[prop];
  504. } else {
  505. return this[symbol];
  506. }
  507. },
  508. set(nv) {
  509. const p = f(this);
  510. if (p) {
  511. p[prop] = nv;
  512. } else {
  513. objSet.add(this);
  514. this[symbol] = nv;
  515. }
  516. return true;
  517. },
  518. enumerable: false,
  519. configurable: true
  520. });
  521.  
  522. };
  523.  
  524. const mediaNetworkStateReady = async (audio) => {
  525.  
  526. if (!(audio instanceof HTMLMediaElement)) {
  527. return '';
  528. }
  529. let done = false;
  530. const et = await Promise.race([
  531.  
  532. new Promise(resolve => {
  533. audio.addEventListener('timeupdate', (evt) => {
  534. !done && resolve && resolve(evt.type);
  535. resolve = null
  536. }, { once: true, capture: true, passive: true })
  537. }),
  538.  
  539. new Promise(resolve => {
  540. audio.addEventListener('waiting', (evt) => {
  541. !done && resolve && resolve(evt.type);
  542. resolve = null
  543. }, { once: true, capture: true, passive: true })
  544. }),
  545.  
  546. new Promise(resolve => {
  547. audio.addEventListener('loadstart', (evt) => {
  548. !done && resolve && resolve(evt.type);
  549. resolve = null
  550. }, { once: true, capture: true, passive: true })
  551. }),
  552.  
  553. new Promise(resolve => {
  554. audio.addEventListener('durationchange', (evt) => {
  555. !done && resolve && resolve(evt.type);
  556. resolve = null
  557. }, { once: true, capture: true, passive: true })
  558. })
  559.  
  560. ]);
  561. done = true;
  562. return et;
  563.  
  564. };
  565.  
  566. const updateLastActiveTimeAsync = (player_) => {
  567. // TBC
  568. Promise.resolve().then(() => {
  569. if (typeof player_.updateLastActiveTime === 'function') {
  570. player_.updateLastActiveTime();
  571. }
  572. });
  573. };
  574.  
  575. const attachOneTimeEvent = function (eventType, callback) {
  576. let kz = false;
  577. document.addEventListener(eventType, function (evt) {
  578. if (kz) return;
  579. kz = true;
  580. callback(evt);
  581. }, { capture: true, passive: true, once: true });
  582. }
  583.  
  584. function removeTempObjectProp01() {
  585. delete Object.prototype['kevlar_non_watch_unified_player'];
  586. delete Object.prototype['kevlar_unified_player'];
  587. }
  588.  
  589. function ytConfigFix(config__) {
  590. const config_ = config__;
  591.  
  592. if (config_) {
  593.  
  594. const playerKevlar = ((config_ || 0).WEB_PLAYER_CONTEXT_CONFIGS || 0).WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH || 0;
  595.  
  596. if (playerKevlar) {
  597.  
  598. // console.log(322, playerKevlar)
  599. playerKevlar.allowWoffleManagement = false;
  600. playerKevlar.cinematicSettingsAvailable = false;
  601. playerKevlar.showMiniplayerButton = false;
  602. playerKevlar.showMiniplayerUiWhenMinimized = false;
  603. playerKevlar.transparentBackground = false;
  604.  
  605. playerKevlar.enableCsiLogging = false;
  606. playerKevlar.externalFullscreen = false;
  607.  
  608. if (typeof playerKevlar.serializedExperimentFlags === 'string') {
  609. playerKevlar.serializedExperimentFlags = '';
  610. // playerKevlar.serializedExperimentFlags = playerKevlar.serializedExperimentFlags.replace(/[-\w]+=(\[\]|[.-\d]+|[_a-z]+|)(&|$)/g,'').replace(/&$/,'')
  611. }
  612.  
  613. if (typeof playerKevlar.serializedExperimentIds === 'string') {
  614. playerKevlar.serializedExperimentIds = '';
  615. // playerKevlar.serializedExperimentIds = playerKevlar.serializedExperimentIds.replace(/\d+\s*(,\s*|$)/g,'')
  616. }
  617.  
  618. }
  619.  
  620. removeTempObjectProp01();
  621.  
  622. let configs = config_.WEB_PLAYER_CONTEXT_CONFIGS || {};
  623. for (const [key, entry] of Object.entries(configs)) {
  624.  
  625. if (entry && typeof entry.serializedExperimentFlags === 'string' && entry.serializedExperimentFlags.length > 16) {
  626. // prevent idle playback failure
  627. 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) => {
  628. return a + '00' + '=' + b + c;
  629. });
  630.  
  631. }
  632.  
  633. }
  634.  
  635. const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS;
  636.  
  637. if (EXPERIMENT_FLAGS) {
  638. EXPERIMENT_FLAGS.kevlar_unified_player = true;
  639. EXPERIMENT_FLAGS.kevlar_non_watch_unified_player = true;
  640. }
  641.  
  642.  
  643. const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS;
  644.  
  645. if (EXPERIMENTS_FORCED_FLAGS) {
  646. EXPERIMENTS_FORCED_FLAGS.kevlar_unified_player = true;
  647. EXPERIMENTS_FORCED_FLAGS.kevlar_non_watch_unified_player = true;
  648. }
  649.  
  650. }
  651. }
  652.  
  653. Object.defineProperty(Object.prototype, 'kevlar_non_watch_unified_player', {
  654. get() {
  655. // console.log(501, this.constructor.prototype)
  656. return true;
  657. },
  658. set(nv) {
  659. return true;
  660. },
  661. enumerable: false,
  662. configurable: true
  663. });
  664.  
  665.  
  666. Object.defineProperty(Object.prototype, 'kevlar_unified_player', {
  667. get() {
  668. // console.log(501, this.constructor.prototype)
  669. return true;
  670. },
  671. set(nv) {
  672. return true;
  673. },
  674. enumerable: false,
  675. configurable: true
  676. });
  677.  
  678. let prr = new PromiseExternal();
  679. const prrPipeline = createPipeline();
  680. let stopAndReload = false;
  681.  
  682. let fa = 0;
  683.  
  684. let cv = null;
  685. let durationchangeForMobile = false;
  686. function fixThumbnailURL(src) {
  687. if (typeof src === 'string' && src.length >= 4) {
  688. let m = /\b[a-z0-9]{4,13}\.jpg\b/.exec(src);
  689. if (m && m[0]) {
  690. const t = m[0];
  691. let idx = src.indexOf(t);
  692. let nSrc = idx >= 0 ? src.substring(0, idx + t.length) : '';
  693. return nSrc;
  694. }
  695. }
  696. return src;
  697. }
  698.  
  699. const isDesktopSite = location.origin === 'https://www.youtube.com' && !location.pathname.startsWith('/embed/');
  700.  
  701. const getThumbnailUrlFromThumbnails = (thumbnails) => {
  702.  
  703. let thumbnailUrl = '';
  704. if (thumbnails && thumbnails.length >= 1) {
  705. const arr = thumbnails.map(e => {
  706. return e.url ? [e.width * e.height, e.url] : typeof e === 'string' ? [0, e] : [0, '']
  707. });
  708. arr.sort((a, b) => b[0] - a[0]);
  709. thumbnailUrl = arr[0][1]
  710. if (typeof thumbnailUrl === 'string') {
  711. thumbnailUrl = fixThumbnailURL(thumbnailUrl);
  712. }
  713. }
  714. return thumbnailUrl;
  715. }
  716.  
  717. const pmof = () => {
  718.  
  719. if (SHOW_VIDEO_STATIC_IMAGE) {
  720.  
  721. const medias = [...document.querySelectorAll('ytd-watch-flexy #player .html5-video-container .video-stream.html5-main-video')].filter(e => !e.closest('[hidden]'));
  722. if (medias.length !== 1) return;
  723. const mediaElement = medias[0];
  724.  
  725. const container = mediaElement ? mediaElement.closest('.html5-video-container') : null;
  726. if (!container) return;
  727.  
  728. let thumbnailUrl = '';
  729. const ytdPage = container.closest('ytd-watch-flexy');
  730. if (ytdPage && ytdPage.is === 'ytd-watch-flexy') {
  731. const cnt = insp(ytdPage);
  732. let thumbnails = null;
  733. try {
  734. thumbnails = cnt.polymerController.__data.playerData.videoDetails.thumbnail.thumbnails
  735. // thumbnails = cnt.__data.watchNextData.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer.background.thumbnails
  736. } catch (e) { }
  737.  
  738. thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  739. }
  740.  
  741.  
  742. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  743. container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  744. } else {
  745. container.style.removeProperty('--audio-only-thumbnail-image')
  746. }
  747.  
  748. }
  749.  
  750.  
  751. }
  752. const pmo = new MutationObserver(pmof);
  753.  
  754. isDesktopSite && document.addEventListener('yt-navigate-finish', () => {
  755. const ytdWatchFlexy = document.querySelector('ytd-watch-flexy');
  756. if (ytdWatchFlexy) {
  757. pmo.observe(ytdWatchFlexy, { attributes: true });
  758. ytdWatchFlexy.setAttribute('ytzNavigateFinish', Date.now());
  759. }
  760. });
  761. document.addEventListener('durationchange', (evt) => {
  762. const target = (evt || 0).target;
  763. if (!(target instanceof HTMLMediaElement)) return;
  764. const targetClassList = target.classList || 0;
  765. const isPlayerVideo = typeof targetClassList.contains === 'function' ? targetClassList.contains('video-stream') && targetClassList.contains('html5-main-video') : false;
  766.  
  767. if (durationchangeForMobile || isPlayerVideo) {
  768. if (target.readyState !== 1) {
  769. fa = 1;
  770. } else {
  771. fa = 2;
  772. }
  773. }
  774.  
  775. if (isPlayerVideo) {
  776.  
  777. if (target.readyState === 1 && target.networkState === 2) {
  778. target.__spfgs__ = true;
  779. if (cv) {
  780. cv.resolve();
  781. cv = null;
  782. }
  783. } else {
  784. target.__spfgs__ = false;
  785. }
  786.  
  787. if (isDesktopSite) {
  788. const ytdWatchFlexy = document.querySelector('ytd-watch-flexy');
  789. if (ytdWatchFlexy) {
  790. ytdWatchFlexy.setAttribute('ytzMediaDurationChanged', Date.now());
  791. }
  792. }
  793.  
  794. if (onVideoChangeForMobile) {
  795. onVideoChangeForMobile();
  796. }
  797.  
  798. }
  799. }, true);
  800.  
  801.  
  802.  
  803. // XMLHttpRequest.prototype.open299 = XMLHttpRequest.prototype.open;
  804. /*
  805.  
  806. XMLHttpRequest.prototype.open2 = function(method, url, ...args){
  807.  
  808. if (typeof url === 'string' && url.length > 24 && url.includes('/videoplayback?') && url.replace('?', '&').includes('&source=')) {
  809. if (vcc !== vdd) {
  810. vdd = vcc;
  811. window.postMessage({ ZECxh: url.includes('source=yt_live_broadcast') }, "*");
  812. }
  813. }
  814.  
  815. return this.open299(method, url, ...args)
  816. }*/
  817.  
  818.  
  819.  
  820. // desktop only
  821. // document.addEventListener('yt-page-data-fetched', async (evt) => {
  822.  
  823. // const pageFetchedDataLocal = evt.detail;
  824. // let isLiveNow;
  825. // try {
  826. // isLiveNow = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.isLiveNow;
  827. // } catch (e) { }
  828. // window.postMessage({ ZECxh: isLiveNow === true }, "*");
  829.  
  830. // }, false);
  831.  
  832. // return;
  833.  
  834. // let clickLockFn = null;
  835.  
  836.  
  837. let onVideoChangeForMobile = null;
  838.  
  839. let removeBottomOverlayForMobile = null;
  840.  
  841. let clickLockFn = null;
  842. let clickTarget = null;
  843. if (location.origin === 'https://m.youtube.com') {
  844.  
  845. EventTarget.prototype.addEventListener322 = EventTarget.prototype.addEventListener;
  846.  
  847. const dummyFn = () => { };
  848. EventTarget.prototype.addEventListener = function (evt, fn, opts) {
  849.  
  850. let hn = fn;
  851.  
  852. // if (evt === 'player-error') {
  853. // } else if (evt === 'player-detailed-error') {
  854. // } else if (evt === 'video-data-change') {
  855. // } else if (evt === 'player-state-change') {
  856. // } else
  857. if (evt === 'player-autonav-pause' || evt === 'visibilitychange') {
  858. evt += 'y'
  859. fn = dummyFn;
  860. } else if (evt === 'click' && this.id === 'movie_player') {
  861. clickLockFn = fn;
  862. clickTarget = this;
  863. }
  864. return this.addEventListener322(evt, hn, opts)
  865.  
  866. }
  867.  
  868. }
  869.  
  870.  
  871.  
  872. (() => {
  873.  
  874. XMLHttpRequest = (() => {
  875. const XMLHttpRequest_ = XMLHttpRequest;
  876. if ('__xmMc8__' in XMLHttpRequest_.prototype) return XMLHttpRequest_;
  877. const url0 = createObjectURL(new Blob([], { type: 'text/plain' }));
  878. const c = class XMLHttpRequest extends XMLHttpRequest_ {
  879. constructor(...args) {
  880. super(...args);
  881. }
  882. open(method, url, ...args) {
  883. let skip = false;
  884. if (!url || typeof url !== 'string') skip = true;
  885. else if (typeof url === 'string') {
  886. let turl = url[0] === '/' ? `.youtube.com${url}` : `${url}`;
  887. if (turl.includes('googleads') || turl.includes('doubleclick.net')) {
  888. skip = true;
  889. } else if (turl.includes('.youtube.com/pagead/')) {
  890. skip = true;
  891. } else if (turl.includes('.youtube.com/ptracking')) {
  892. skip = true;
  893. } else if (turl.includes('.youtube.com/api/stats/')) { // /api/stats/
  894. // skip = true; // for user activity logging e.g. watched videos
  895. } else if (turl.includes('play.google.com/log')) {
  896. skip = true;
  897. } else if (turl.includes('.youtube.com//?')) { // //?cpn=
  898. skip = true;
  899. }
  900. }
  901. if (!skip) {
  902. this.__xmMc8__ = 1;
  903. return super.open(method, url, ...args);
  904. } else {
  905. this.__xmMc8__ = 2;
  906. return super.open('GET', url0);
  907. }
  908. }
  909. send(...args) {
  910. if (this.__xmMc8__ === 1) {
  911. return super.send(...args);
  912. } else if (this.__xmMc8__ === 2) {
  913. return super.send();
  914. } else {
  915. console.log('xhr warning');
  916. return super.send(...args);
  917. }
  918. }
  919. }
  920. c.prototype.__xmMc8__ = 0;
  921. prototypeInherit(c.prototype, XMLHttpRequest_.prototype);
  922. return c;
  923. })();
  924.  
  925. const s7 = Symbol();
  926. const f7 = () => true;
  927.  
  928. !window.canRetry9048 && generalRegister('canRetry', s7, (p) => {
  929. 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'
  930. }, {
  931. get() {
  932. if ('logger' in this && 'policy' in this && 'xhr' && this) {
  933. 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"
  934. // OKAY !
  935. console.log('canRetry05 - ', this.errorMessage)
  936. return f7;
  937. }
  938. // console.log(this)
  939. console.log('canRetry02 - ', this.errorMessage, this)
  940. } else {
  941. console.log('canRetry ERR - ', this.errorMessage)
  942. }
  943. return this[s7];
  944. },
  945. set(nv) {
  946. this[s7] = nv;
  947. return true;
  948. },
  949. enumerable: false,
  950. configurable: true
  951. });
  952. window.canRetry9048 = 1;
  953.  
  954. })();
  955.  
  956. if (location.origin === 'https://www.youtube.com') {
  957.  
  958. if (location.pathname.startsWith('/embed/')) {
  959.  
  960. const ytEmbedReady = observablePromise(() => document.querySelector('#player > .ytp-embed')).obtain();
  961.  
  962. const embedConfigFix = (async () => {
  963. while (true) {
  964. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  965. if (config_) {
  966. ytConfigFix(config_);
  967. break;
  968. }
  969. await delayPn(60);
  970. }
  971. });
  972.  
  973. ytEmbedReady.then(async (embedPlayer) => {
  974.  
  975. embedConfigFix();
  976.  
  977. const player_ = embedPlayer;
  978. // console.log(player_)
  979.  
  980. const asyncStateChange = async (audio, k) => {
  981. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  982. try {
  983. if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  984. } catch (e) {
  985. }
  986. };
  987. const triggerPlaying = async () => {
  988. await player_.pauseVideo();
  989. await player_.playVideo();
  990. };
  991. const seekToLiveHeadForLiveStream = async () => {
  992. try {
  993. await player_.seekToLiveHead();
  994. if ((await player_.isAtLiveHead()) === true) {
  995. await player_.seekToStreamTime();
  996. return true;
  997. }
  998. } catch (e) {
  999. console.log('error_F3', e);
  1000. }
  1001. };
  1002. const fixLiveAudioFn = async () => {
  1003. if (audio.paused === true) {
  1004.  
  1005. await player_.clearVideo(); // avoid error in live streaming
  1006. await player_.clearQueue(); // avoid error in live streaming
  1007. await delayPn(300);
  1008. for (let i = 0; i < 3; i++) {
  1009. if (audio.readyState === 0) {
  1010. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1011. }
  1012. }
  1013. if (k === -1) {
  1014. await refreshAllStaleEntitiesForNonReadyAudio();
  1015. } else if (k === 3) {
  1016. while (audio.readyState === 0) {
  1017. await refreshAllStaleEntitiesForNonReadyAudio();
  1018. await triggerPlaying();
  1019. await delayPn(300);
  1020. }
  1021. }
  1022. } else if (audio.paused === false) {
  1023.  
  1024. if (!player_.isAtLiveHead()) {
  1025. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1026. }
  1027. while (audio.readyState === 0) {
  1028. await refreshAllStaleEntitiesForNonReadyAudio();
  1029. await triggerPlaying();
  1030. await delayPn(300);
  1031. }
  1032. if (!player_.isAtLiveHead()) {
  1033. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1034. }
  1035. await refreshAllStaleEntitiesForNonReadyAudio();
  1036. if (audio.readyState > 0 && audio.paused === true) {
  1037. await triggerPlaying();
  1038. }
  1039. }
  1040.  
  1041. }
  1042. try {
  1043. let ns23 = audio.networkState == 2 || audio.networkState == 3;
  1044.  
  1045. if (!ns23 && k === player_.getPlayerState()) {
  1046. if (k === -1 && audio.readyState === 0) {
  1047. const et = await mediaNetworkStateReady(audio);
  1048. if (audio.isConnected === false || player_.getPlayerState() === 5) return;
  1049. ns23 = audio.networkState == 2 || audio.networkState == 3;
  1050. // console.log(503, ns23, et, player_.getPlayerState());
  1051. if (player_.getPlayerState() !== -1) return;
  1052. } else {
  1053. console.log(507, k, audio.readyState, audio.networkState)
  1054. }
  1055. }
  1056.  
  1057. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1058. await delayPn(200);
  1059. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1060. await fixLiveAudioFn();
  1061. }
  1062. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1063. await seekToLiveHeadForLiveStream();
  1064. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  1065. await delayPn(60);
  1066. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  1067. await fixLiveAudioFn();
  1068. }
  1069. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  1070. await seekToLiveHeadForLiveStream();
  1071. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  1072. await delayPn(60);
  1073. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  1074. await fixLiveAudioFn();
  1075. }
  1076. }
  1077.  
  1078. } catch (e) {
  1079. console.log('error_F4', e)
  1080. }
  1081.  
  1082. };
  1083.  
  1084. // console.log(299, player_)
  1085. const _onPlayerStateChange = (k) => {
  1086. try {
  1087. if (typeof k === 'number' && k === player_.getPlayerState()) {
  1088.  
  1089. const audio = document.querySelector('#player audio.video-stream.html5-main-video');
  1090. if (audio) asyncStateChange(audio, k);
  1091.  
  1092. }
  1093. } catch (e) {
  1094. console.log('error_F5', e)
  1095. }
  1096. };
  1097.  
  1098. player_.addEventListener('onStateChange', _onPlayerStateChange);
  1099. const state0 = player_.getPlayerState();
  1100. if (typeof state0 === 'number') {
  1101. _onPlayerStateChange(state0);
  1102. }
  1103.  
  1104. player_.addEventListener('onVideoProgress', () => {
  1105. updateLastActiveTimeAsync(player_);
  1106. });
  1107.  
  1108. // console.log(1231)
  1109.  
  1110. if (SHOW_VIDEO_STATIC_IMAGE) {
  1111.  
  1112. let displayImage = '';
  1113. let html5Container = null;
  1114.  
  1115.  
  1116. const moviePlayer = document.querySelector('#movie_player .html5-video-container .video-stream.html5-main-video');
  1117. if (moviePlayer) {
  1118. html5Container = moviePlayer.closest('.html5-video-container');
  1119. }
  1120.  
  1121. if (html5Container) {
  1122.  
  1123. const overlayImage = document.querySelector('#movie_player .ytp-cued-thumbnail-overlay-image[style]');
  1124. if (overlayImage) {
  1125.  
  1126. const cStyle = window.getComputedStyle(overlayImage);
  1127. const cssImageValue = cStyle.backgroundImage;
  1128. if (cssImageValue && typeof cssImageValue === 'string' && cssImageValue.startsWith('url(')) {
  1129. displayImage = cssImageValue;
  1130.  
  1131. }
  1132.  
  1133. }
  1134.  
  1135. if (!displayImage) {
  1136.  
  1137. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1138. let embedded_player_response = null;
  1139. if (config_) {
  1140. embedded_player_response = ((config_.PLAYER_VARS || 0).embedded_player_response || 0)
  1141. }
  1142. if (embedded_player_response && typeof embedded_player_response === 'string') {
  1143.  
  1144. let idx1 = embedded_player_response.indexOf('"defaultThumbnail"');
  1145. let idx2 = idx1 >= 0 ? embedded_player_response.lastIndexOf('"defaultThumbnail"') : -1;
  1146.  
  1147. if (idx1 === idx2 && idx1 > 0) {
  1148.  
  1149. let bk = 0;
  1150. let j = -1;
  1151. for (let i = idx1; i < embedded_player_response.length; i++) {
  1152. if (i > idx1 + 40 && bk === 0) {
  1153. j = i;
  1154. break;
  1155. }
  1156. let t = embedded_player_response.charAt(i);
  1157. if (t === '{') bk++;
  1158. else if (t === '}') bk--;
  1159. }
  1160.  
  1161. if (j > idx1) {
  1162.  
  1163. let defaultThumbnailString = embedded_player_response.substring(idx1, j);
  1164. let defaultThumbnailObject = null;
  1165.  
  1166. try {
  1167. defaultThumbnailObject = JSON.parse(`{${defaultThumbnailString}}`);
  1168.  
  1169. } catch (e) { }
  1170.  
  1171. const thumbnails = ((defaultThumbnailObject.defaultThumbnail || 0).thumbnails || 0);
  1172.  
  1173. if (thumbnails && thumbnails.length >= 1) {
  1174.  
  1175. let thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1176.  
  1177. if (thumbnailUrl && thumbnailUrl.length > 3) {
  1178. displayImage = `url(${thumbnailUrl})`;
  1179. }
  1180. }
  1181. }
  1182.  
  1183. }
  1184.  
  1185.  
  1186. }
  1187.  
  1188.  
  1189. }
  1190.  
  1191. if (displayImage) {
  1192.  
  1193. html5Container.style.setProperty('--audio-only-thumbnail-image', `${displayImage}`);
  1194. } else {
  1195. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1196. }
  1197.  
  1198. }
  1199.  
  1200.  
  1201. }
  1202.  
  1203. });
  1204.  
  1205.  
  1206. } else {
  1207.  
  1208. attachOneTimeEvent('yt-action', () => {
  1209. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1210. ytConfigFix(config_);
  1211. });
  1212.  
  1213. const setupAudioPlaying = (player00_) => {
  1214. const player_ = player00_;
  1215. if (!player_) return;
  1216. if (player_.__audio544__) return;
  1217. player_.__audio544__ = 1;
  1218.  
  1219. globalPlayer = mWeakRef(player_);
  1220.  
  1221. // console.log(1233, player_)
  1222. const mediaCollection = document.getElementsByClassName('html5-main-video');
  1223.  
  1224. const stopAndReloadFn = async () => {
  1225. let isLive = false;
  1226. if (isWatchPageURL()) {
  1227. const liveBtn = document.querySelector('.ytp-live-badge.ytp-button');
  1228. try {
  1229. if (liveBtn && !liveBtn.closest('[hidden]') && (liveBtn.textContent || '').trim().length > 0) {
  1230. isLive = true;
  1231. }
  1232. } catch (e) { }
  1233. }
  1234. if (isLive) {
  1235. player_.destroy();
  1236. location.replace(location.href);
  1237. await delayPn(8000);
  1238. } else {
  1239. // await player_.stopVideo();
  1240. // await player_.updateVideoData();
  1241. // try{
  1242. // await player_.refreshAllStaleEntities();
  1243. // }catch(e){}
  1244. // await player_.playVideo();
  1245. }
  1246. };
  1247. const asyncStateChange = async (audio, k) => {
  1248.  
  1249. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1250. try {
  1251. if (audio.readyState == 0 && audio.isConnected === true) await player_.refreshAllStaleEntities();
  1252. } catch (e) {
  1253. }
  1254. };
  1255. const triggerPlaying = async () => {
  1256. await player_.cancelPlayback();
  1257. await player_.pauseVideo();
  1258. await player_.playVideo();
  1259. };
  1260. const seekToLiveHeadForLiveStream = async () => {
  1261. try {
  1262. audio.isConnected === true && await player_.seekToLiveHead();
  1263. if (audio.isConnected === true && (await player_.isAtLiveHead()) === true) {
  1264. audio.isConnected === true && await player_.seekToStreamTime();
  1265. return true;
  1266. }
  1267. } catch (e) {
  1268. console.log('error_F7', e);
  1269. }
  1270. };
  1271. const fixLiveAudioFn = async () => {
  1272. if (stopAndReload) {
  1273. stopAndReload = false;
  1274. await stopAndReloadFn();
  1275. }
  1276. if (audio.isConnected === true && audio.paused === true) {
  1277. await player_.clearVideo(); // avoid error in live streaming
  1278. await player_.clearQueue(); // avoid error in live streaming
  1279. await delayPn(300);
  1280. for (let i = 0; i < 3; i++) {
  1281. if (audio.readyState === 0 && audio.isConnected === true) {
  1282. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1283. }
  1284. }
  1285. if (k === -1) {
  1286. await refreshAllStaleEntitiesForNonReadyAudio();
  1287. } else if (k === 3) {
  1288. while (audio.readyState === 0 && audio.isConnected === true) {
  1289. await refreshAllStaleEntitiesForNonReadyAudio();
  1290. await triggerPlaying();
  1291. await delayPn(300);
  1292. }
  1293. }
  1294. } else if (audio.isConnected === true && audio.paused === false) {
  1295. if (!player_.isAtLiveHead() && audio.isConnected === true) {
  1296. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1297. }
  1298. while (audio.readyState === 0 && audio.isConnected === true) {
  1299. await refreshAllStaleEntitiesForNonReadyAudio();
  1300. await triggerPlaying();
  1301. await delayPn(300);
  1302. }
  1303. if (!player_.isAtLiveHead() && audio.isConnected === true) {
  1304. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1305. }
  1306. await refreshAllStaleEntitiesForNonReadyAudio();
  1307. if (audio.readyState > 0 && audio.paused === true && audio.isConnected === true) {
  1308. await triggerPlaying();
  1309. }
  1310. }
  1311. }
  1312. try {
  1313.  
  1314. let ns23 = audio.networkState == 2 || audio.networkState == 3;
  1315.  
  1316. if (!ns23 && k === player_.getPlayerState()) {
  1317. if (k === -1 && audio.readyState === 0) {
  1318. const et = await mediaNetworkStateReady(audio);
  1319. if (audio.isConnected === false || player_.getPlayerState() === 5) return;
  1320. ns23 = audio.networkState == 2 || audio.networkState == 3;
  1321. console.log(513, ns23, et, player_.getPlayerState());
  1322. if (player_.getPlayerState() !== -1) return;
  1323. } else if (k === 3 && audio.readyState === 0 && audio.networkState === 0) {
  1324. const et = await Promise.race([mediaNetworkStateReady(audio), delayPn(800)]); // idk
  1325. if (audio.isConnected === false || player_.getPlayerState() === 5) return;
  1326. ns23 = audio.networkState == 2 || audio.networkState == 3;
  1327. console.log(514, ns23, et, player_.getPlayerState());
  1328. if (player_.getPlayerState() !== 3) return;
  1329. } else {
  1330. console.log(517, k, audio.readyState, audio.networkState) // 517 3 0 0 after tab sleeping
  1331. }
  1332. }
  1333.  
  1334. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1335. await delayPn(200);
  1336. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1337. await fixLiveAudioFn();
  1338. }
  1339. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1340. await seekToLiveHeadForLiveStream();
  1341. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  1342. await delayPn(60);
  1343. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  1344. await fixLiveAudioFn();
  1345. }
  1346. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  1347. await seekToLiveHeadForLiveStream();
  1348. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  1349. await delayPn(60);
  1350. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  1351. await fixLiveAudioFn();
  1352. }
  1353. }
  1354.  
  1355. } catch (e) {
  1356. console.log('error_F8', e)
  1357. }
  1358.  
  1359. };
  1360. let mid = 0;
  1361. const getAudioElement = () => {
  1362. if (mediaCollection.length === 0) return null;
  1363. if (mediaCollection.length > 1) {
  1364. const audios = [...mediaCollection].filter(e => e && !e.closest('[hidden]') && e.closest('ytd-player'));
  1365. if (audios.length === 1) {
  1366. return audios[0];
  1367. }
  1368. } else if (mediaCollection.length === 1) {
  1369. const e = mediaCollection[0];
  1370. if (e && !e.closest('[hidden]') && e.closest('ytd-player')) return e;
  1371. }
  1372. return null;
  1373. };
  1374. const _onPlayerStateChange = (k_) => {
  1375. const k = k_;
  1376. const ps = player_.getPlayerState();
  1377. if (stopAndReload) {
  1378. stopAndReload = false;
  1379. const audio = getAudioElement();
  1380. if (audio) {
  1381. prrPipeline(async () => {
  1382. await prr.then();
  1383. await stopAndReloadFn();
  1384. });
  1385. }
  1386. }
  1387. if (typeof k === 'number' && k === ps && ps !== 5) {
  1388.  
  1389. if (mid > 1e9) mid = 9;
  1390. const t = ++mid;
  1391. prrPipeline(async () => {
  1392. if (t !== mid) return;
  1393. await prr.then();
  1394. if (t !== mid) return;
  1395. const audio = getAudioElement();
  1396.  
  1397. if (audio && player_.getPlayerState() === ps) {
  1398. await asyncStateChange(audio, k);
  1399. }
  1400. });
  1401. }
  1402. };
  1403.  
  1404. player_.addEventListener('onStateChange', _onPlayerStateChange);
  1405. const state0 = player_.getPlayerState();
  1406. // console.log(221, state0)
  1407. if (typeof state0 === 'number') {
  1408. _onPlayerStateChange(state0);
  1409. }
  1410.  
  1411. player_.addEventListener('onVideoProgress', () => {
  1412. updateLastActiveTimeAsync(player_);
  1413. });
  1414.  
  1415. }
  1416.  
  1417. customElements.whenDefined('ytd-player').then(() => {
  1418. const dummy = document.querySelector('ytd-player') || document.createElement('ytd-player');
  1419. const cnt = insp(dummy);
  1420. const cProto = cnt.constructor.prototype;
  1421. cProto.createMainAppPlayer932_ = cProto.createMainAppPlayer_;
  1422. cProto.initPlayer932_ = cProto.initPlayer_;
  1423. const configFixBeforeCreate = () => {
  1424. try {
  1425. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1426. if (config_) {
  1427. ytConfigFix(config_);
  1428. }
  1429. } catch (e) { }
  1430. }
  1431. cProto.createMainAppPlayer_ = function (a, b, c) {
  1432. configFixBeforeCreate();
  1433. let r = this.createMainAppPlayer932_(a, b, c);
  1434. try {
  1435. this.mainAppPlayer_.api.then(function (e) {
  1436. setupAudioPlaying(e);
  1437. })
  1438. } finally {
  1439. return r;
  1440. }
  1441. }
  1442. cProto.initPlayer_ = function (a) {
  1443. configFixBeforeCreate();
  1444. let r = this.initPlayer932_(a);
  1445. try {
  1446. r.then(() => {
  1447. setupAudioPlaying(this.player_);
  1448. })
  1449. } finally {
  1450. return r;
  1451. }
  1452. }
  1453. })
  1454.  
  1455. let useStopAndReload = !isWatchPageURL();
  1456. document.addEventListener('yt-navigate-start', () => {
  1457. prr = new PromiseExternal();
  1458. if (useStopAndReload) stopAndReload = true;
  1459. });
  1460.  
  1461. document.addEventListener('yt-navigate-cache', () => {
  1462. prr = new PromiseExternal();
  1463. if (useStopAndReload) stopAndReload = true;
  1464. });
  1465.  
  1466. document.addEventListener('yt-navigate-finish', () => {
  1467. prr.resolve();
  1468. });
  1469.  
  1470. }
  1471.  
  1472. } else if (location.origin === 'https://m.youtube.com') {
  1473.  
  1474. removeBottomOverlayForMobile = async (delay) => {
  1475.  
  1476.  
  1477. let closeBtnRenderer = document.querySelector('.ytm-bottom-sheet-overlay-renderer-close.icon-close');
  1478. if (closeBtnRenderer) {
  1479.  
  1480. const btn = closeBtnRenderer.querySelector('button');
  1481. const container = closeBtnRenderer.closest('#global-loader ~ .ytm-bottom-sheet-overlay-container');
  1482.  
  1483. if (container) {
  1484. container.style.visibility = 'collapse';
  1485. container.style.zIndex = '-1';
  1486. }
  1487. if (btn) {
  1488. if (delay) {
  1489. await delayPn(delay);
  1490. }
  1491. btn.click();
  1492. }
  1493. }
  1494.  
  1495. }
  1496.  
  1497.  
  1498. let lastPlayerInfoText = '';
  1499. let mz = 0;
  1500. onVideoChangeForMobile = async () => {
  1501.  
  1502.  
  1503. let html5Container = null;
  1504.  
  1505. const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video');
  1506. if (moviePlayer) {
  1507. html5Container = moviePlayer.closest('.html5-video-container');
  1508. }
  1509. if (!html5Container) return;
  1510. let thumbnailUrl = '';
  1511.  
  1512. if (mz > 1e9) mz = 9;
  1513. let mt = ++mz;
  1514. const scriptText = await observablePromise(() => {
  1515. if (mt !== mz) return 1;
  1516. const t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]');
  1517. const tt = (t ? t.textContent : '') || '';
  1518. if (tt === lastPlayerInfoText) return;
  1519. return tt;
  1520. }).obtain();
  1521. if (typeof scriptText !== 'string') return; // 1
  1522. lastPlayerInfoText = scriptText;
  1523.  
  1524. if (!scriptText) return;
  1525.  
  1526.  
  1527. if (SHOW_VIDEO_STATIC_IMAGE) {
  1528.  
  1529. let idx1 = scriptText.indexOf('"thumbnailUrl"');
  1530. let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1;
  1531.  
  1532. if (idx1 === idx2 && idx1 > 0) {
  1533.  
  1534. let bk = 0;
  1535. let j = -1;
  1536. for (let i = idx1; i < scriptText.length; i++) {
  1537. if (i > idx1 + 20 && bk === 0) {
  1538. j = i;
  1539. break;
  1540. }
  1541. let t = scriptText.charAt(i);
  1542. if (t === '[') bk++;
  1543. else if (t === ']') bk--;
  1544. else if (t === '{') bk++;
  1545. else if (t === '}') bk--;
  1546. }
  1547.  
  1548.  
  1549. if (j > idx1) {
  1550.  
  1551. let thumbnailUrlString = scriptText.substring(idx1, j);
  1552. let thumbnailUrlObject = null;
  1553.  
  1554. try {
  1555. thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`);
  1556.  
  1557. } catch (e) { }
  1558.  
  1559. const thumbnails = thumbnailUrlObject.thumbnailUrl;
  1560.  
  1561. if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') {
  1562. if (thumbnails[0] && thumbnails[0].length > 3) {
  1563. thumbnailUrl = thumbnails[0];
  1564. }
  1565. }
  1566. }
  1567.  
  1568. }
  1569.  
  1570. // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0;
  1571.  
  1572. // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0);
  1573.  
  1574. // if (thumbnails && thumbnails.length >= 1) {
  1575. // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1576.  
  1577. // }
  1578. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  1579. html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  1580. } else {
  1581. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1582. }
  1583.  
  1584. }
  1585.  
  1586.  
  1587. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40);
  1588.  
  1589. await delayPn(80);
  1590. const audio = moviePlayer;
  1591. if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) {
  1592. await audio.click();
  1593. }
  1594.  
  1595. }
  1596.  
  1597. let player0 = null;
  1598. let mgg = null;
  1599. const mff = function (e) {
  1600. if (!player0) {
  1601. if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') {
  1602. player0 = e.target
  1603. if (mgg) mgg();
  1604. }
  1605. }
  1606.  
  1607.  
  1608. // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) {
  1609.  
  1610. // onVideoChangeForMobile();
  1611. // }
  1612.  
  1613. }
  1614.  
  1615. document.addEventListener('player-initialized', mff, true);
  1616. document.addEventListener('player-state-change', mff, true);
  1617. document.addEventListener('player-ad-state-change', mff, true);
  1618. document.addEventListener('player-detailed-error', mff, true);
  1619. document.addEventListener('player-error', mff, true);
  1620. document.addEventListener('on-play-autonav-video', mff, true);
  1621. document.addEventListener('on-play-previous-autonav-video', mff, true);
  1622. document.addEventListener('player-fullscreen-change', mff, true);
  1623. document.addEventListener('player-fullscreen-toggled', mff, true);
  1624. document.addEventListener('player-dom-paused', mff, true);
  1625. document.addEventListener('yt-show-toast', mff, true);
  1626. document.addEventListener('yt-innertube-command', mff, true);
  1627. document.addEventListener('yt-update-c3-companion', mff, true);
  1628. document.addEventListener('video-data-change', mff, true);
  1629. document.addEventListener('video-progress', mff, true);
  1630. document.addEventListener('local-media-change', mff, true);
  1631.  
  1632.  
  1633. let tc = false;
  1634. // let pw = null;
  1635. (async () => {
  1636.  
  1637. let player__;
  1638.  
  1639. const getAudioElement = () => {
  1640. const elm = player__ || player0;
  1641. const audio = elm && elm.isConnected === true ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null;
  1642. return audio;
  1643. }
  1644.  
  1645. const asyncStateChange = async (audio, k) => {
  1646. const player_ = player__;
  1647. if (!player_) return;
  1648. if (typeof player_.getPlayerState !== 'function') return;
  1649.  
  1650. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1651. // try {
  1652. // if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  1653. // } catch (e) {
  1654. // }
  1655. };
  1656. const triggerPlaying = async () => {
  1657. await player_.cancelPlayback();
  1658. await player_.pauseVideo();
  1659. await player_.playVideo();
  1660. };
  1661. const seekToLiveHeadForLiveStream = async () => {
  1662. try {
  1663. await player_.seekToLiveHead();
  1664. if ((await player_.isAtLiveHead()) === true) {
  1665. await player_.seekToStreamTime();
  1666. return true;
  1667. }
  1668. } catch (e) {
  1669. console.log('error_F9', e);
  1670. }
  1671. };
  1672. const fixLiveAudioFn = async () => {
  1673. if (audio.paused === true) {
  1674. await player_.clearVideo(); // avoid error in live streaming
  1675. await player_.clearQueue(); // avoid error in live streaming
  1676. await delayPn(300);
  1677. for (let i = 0; i < 3; i++) {
  1678. if (audio.readyState === 0) {
  1679. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1680. }
  1681. }
  1682. if (k === -1) {
  1683. await refreshAllStaleEntitiesForNonReadyAudio();
  1684. } else if (k === 3) {
  1685. while (audio.readyState === 0) {
  1686. await refreshAllStaleEntitiesForNonReadyAudio();
  1687. await triggerPlaying();
  1688. await delayPn(300);
  1689. }
  1690. // console.log(8809,audio.readyState)
  1691. }
  1692. } else if (audio.paused === false) {
  1693. if (!player_.isAtLiveHead()) {
  1694. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1695. }
  1696. while (audio.readyState === 0) {
  1697. await refreshAllStaleEntitiesForNonReadyAudio();
  1698. await triggerPlaying();
  1699. await delayPn(300);
  1700. }
  1701. if (!player_.isAtLiveHead()) {
  1702. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1703. }
  1704. await refreshAllStaleEntitiesForNonReadyAudio();
  1705. if (audio.readyState > 0 && audio.paused === true) {
  1706. await triggerPlaying();
  1707. }
  1708. }
  1709.  
  1710. }
  1711. try {
  1712.  
  1713. let ns23 = audio.networkState == 2 || audio.networkState == 3
  1714. // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted)
  1715.  
  1716. if (!ns23 && k === player_.getPlayerState()) {
  1717. if (k === -1 && audio.readyState === 0) {
  1718. const et = await mediaNetworkStateReady(audio);
  1719. if (audio.isConnected === false || player_.getPlayerState() === 5) return;
  1720. ns23 = audio.networkState == 2 || audio.networkState == 3;
  1721. console.log(523, ns23, et, player_.getPlayerState());
  1722. if (player_.getPlayerState() !== -1) return;
  1723. } else {
  1724. console.log(527, k, audio.readyState, audio.networkState)
  1725. }
  1726. }
  1727.  
  1728. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300);
  1729.  
  1730. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) {
  1731. tc = true;
  1732. }
  1733. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1734. await delayPn(200);
  1735. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1736. // console.log(8806)
  1737. await fixLiveAudioFn();
  1738. }
  1739. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1740. await seekToLiveHeadForLiveStream();
  1741. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) {
  1742. await delayPn(60);
  1743. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) {
  1744. // console.log(8807)
  1745. await fixLiveAudioFn();
  1746. }
  1747.  
  1748. }
  1749.  
  1750. } catch (e) {
  1751. console.log('error_F10', e)
  1752. }
  1753.  
  1754. };
  1755. const _onPlayerStateChange = (e) => {
  1756. if (e && (e || 0).target) {
  1757. player__ = e.target
  1758. }
  1759. const player_ = player__;
  1760. try {
  1761. if (!player_) return;
  1762. let k = null;
  1763. if (e && e.detail && e.detail.state) {
  1764. k = e.detail.state
  1765. }
  1766. if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) {
  1767. const audio = getAudioElement();
  1768. if (audio) asyncStateChange(audio, k);
  1769. }
  1770. } catch (e) {
  1771. console.log('error_F11', e)
  1772. }
  1773. };
  1774.  
  1775. let idleAudioActivatePending = false;
  1776.  
  1777. const _onVideoProgress = (e) => {
  1778. if (e && (e || 0).target) {
  1779. player__ = e.target
  1780. }
  1781. const player_ = player__;
  1782. if (!player_) return;
  1783. updateLastActiveTimeAsync(player_);
  1784. if (tc) {
  1785. tc = false;
  1786. if (!idleAudioActivatePending) {
  1787. idleAudioActivatePending = true;
  1788. }
  1789. }
  1790. };
  1791.  
  1792. mgg = function () {
  1793. const player_ = player0;
  1794. if (player_) {
  1795. const state0 = player_.getPlayerState();
  1796. if (typeof state0 === 'number') {
  1797. _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } });
  1798. }
  1799. }
  1800. }
  1801.  
  1802. document.addEventListener('player-state-change', _onPlayerStateChange, true);
  1803.  
  1804. document.addEventListener('video-progress', _onVideoProgress, true);
  1805.  
  1806. })();
  1807.  
  1808. // document.addEventListener('DOMContentLoaded', (evt) => {
  1809. // const mo = new MutationObserver((mutations)=>{
  1810. // console.log(5899, mutations)
  1811. // });
  1812. // mo.observe(document, {subtree: true, childList: true})
  1813. // })
  1814.  
  1815. // window.addEventListener('onReady', (evt) => {
  1816. // console.log(6811)
  1817. // }, true);
  1818.  
  1819. // window.addEventListener('localmediachange', (evt) => {
  1820. // console.log(6812)
  1821. // }, true);
  1822.  
  1823. // window.addEventListener('onVideoDataChange', (evt) => {
  1824. // console.log(6813)
  1825. // }, true);
  1826.  
  1827. window.addEventListener('state-navigateend', async (evt) => {
  1828.  
  1829.  
  1830. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1831. ytConfigFix(config_);
  1832.  
  1833. try {
  1834. if (clickLockFn && clickTarget) {
  1835.  
  1836. let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video');
  1837. if (!a) return;
  1838.  
  1839. if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1840.  
  1841. const pr = new Promise(resolve => {
  1842.  
  1843. document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false });
  1844.  
  1845. }).then();
  1846.  
  1847. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1848. await delayPn(1);
  1849.  
  1850. if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1851. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1852. await delayPn(1);
  1853. }
  1854.  
  1855. delayRun(pr);
  1856.  
  1857. }
  1858.  
  1859. }
  1860.  
  1861. } catch (e) { console.log('error_F12', e) }
  1862.  
  1863.  
  1864. }, false);
  1865.  
  1866.  
  1867.  
  1868. // document.addEventListener('volumechange', (evt) => {
  1869. // console.log('volumechange')
  1870. // }, true)
  1871. // document.addEventListener('play', (evt) => {
  1872. // console.log('play')
  1873. // }, true)
  1874.  
  1875.  
  1876. // document.addEventListener('player-initialized', (evt) => {
  1877. // console.log(evt.type)
  1878. // }, true)
  1879. // document.addEventListener('renderer-module-load-start', (evt) => {
  1880. // console.log(evt.type)
  1881. // }, true)
  1882. // document.addEventListener('video-data-change', (evt) => {
  1883. // console.log(evt.type)
  1884. // }, true)
  1885. // document.addEventListener('player-state-change', (evt) => {
  1886. // console.log(evt.type)
  1887. // }, true)
  1888. // document.addEventListener('updateui', (evt) => {
  1889. // console.log(evt.type)
  1890. // }, true)
  1891. // document.addEventListener('renderer-module-load-end', (evt) => {
  1892. // console.log(evt.type)
  1893. // }, true)
  1894.  
  1895. // document.addEventListener('player-autonav-pause', (evt) => {
  1896. // console.log(evt.type)
  1897. // }, true)
  1898.  
  1899.  
  1900.  
  1901. // document.addEventListener('player-ad-state-change', (evt) => {
  1902. // console.log(evt.type)
  1903. // }, true)
  1904.  
  1905. // document.addEventListener('player-detailed-error', (evt) => {
  1906. // console.log(evt.type)
  1907. // }, true)
  1908.  
  1909. // document.addEventListener('player-error', (evt) => {
  1910. // console.log(evt.type)
  1911. // }, true)
  1912.  
  1913. // document.addEventListener('on-play-autonav-video', (evt) => {
  1914. // console.log(evt.type)
  1915. // }, true)
  1916.  
  1917. // document.addEventListener('on-play-previous-autonav-video', (evt) => {
  1918. // console.log(evt.type)
  1919. // }, true)
  1920.  
  1921. // document.addEventListener('player-fullscreen-change', (evt) => {
  1922. // console.log(evt.type)
  1923. // }, true)
  1924.  
  1925. // document.addEventListener('player-fullscreen-toggled', (evt) => {
  1926. // console.log(evt.type)
  1927. // }, true)
  1928.  
  1929. // document.addEventListener('player-dom-paused', (evt) => {
  1930. // console.log(evt.type)
  1931. // }, true)
  1932.  
  1933. // document.addEventListener('yt-show-toast', (evt) => {
  1934. // console.log(evt.type)
  1935. // }, true)
  1936. // document.addEventListener('yt-innertube-command', (evt) => {
  1937. // console.log(evt.type)
  1938. // }, true)
  1939. // document.addEventListener('yt-update-c3-companion', (evt) => {
  1940. // console.log(evt.type)
  1941. // }, true)
  1942. // document.addEventListener('video-progress', (evt) => {
  1943. // // console.log(evt.type)
  1944. // }, true)
  1945. // document.addEventListener('localmediachange', (evt) => {
  1946. // console.log(evt.type)
  1947. // }, true)
  1948.  
  1949.  
  1950.  
  1951. // window.addEventListener('player-initialized', (evt) => {
  1952. // console.log(evt.type)
  1953. // }, true)
  1954. // window.addEventListener('renderer-module-load-start', (evt) => {
  1955. // console.log(evt.type)
  1956. // }, true)
  1957. // window.addEventListener('video-data-change', (evt) => {
  1958. // console.log(evt.type)
  1959. // }, true)
  1960. // window.addEventListener('player-state-change', (evt) => {
  1961. // console.log(evt.type)
  1962. // }, true)
  1963. // window.addEventListener('updateui', (evt) => {
  1964. // console.log(evt.type)
  1965. // }, true)
  1966. // window.addEventListener('renderer-module-load-end', (evt) => {
  1967. // console.log(evt.type)
  1968. // }, true)
  1969.  
  1970. // window.addEventListener('player-autonav-pause', (evt) => {
  1971. // console.log(evt.type)
  1972. // }, true)
  1973.  
  1974.  
  1975.  
  1976. // window.addEventListener('player-ad-state-change', (evt) => {
  1977. // console.log(evt.type)
  1978. // }, true)
  1979.  
  1980. // window.addEventListener('player-detailed-error', (evt) => {
  1981. // console.log(evt.type)
  1982. // }, true)
  1983.  
  1984. // window.addEventListener('player-error', (evt) => {
  1985. // console.log(evt.type)
  1986. // }, true)
  1987.  
  1988. // window.addEventListener('on-play-autonav-video', (evt) => {
  1989. // console.log(evt.type)
  1990. // }, true)
  1991.  
  1992. // window.addEventListener('on-play-previous-autonav-video', (evt) => {
  1993. // console.log(evt.type)
  1994. // }, true)
  1995.  
  1996. // window.addEventListener('player-fullscreen-change', (evt) => {
  1997. // console.log(evt.type)
  1998. // }, true)
  1999.  
  2000. // window.addEventListener('player-fullscreen-toggled', (evt) => {
  2001. // console.log(evt.type)
  2002. // }, true)
  2003.  
  2004. // window.addEventListener('player-dom-paused', (evt) => {
  2005. // console.log(evt.type)
  2006. // }, true)
  2007.  
  2008. // window.addEventListener('yt-show-toast', (evt) => {
  2009. // console.log(evt.type)
  2010. // }, true)
  2011. // window.addEventListener('yt-innertube-command', (evt) => {
  2012. // console.log(evt.type)
  2013. // }, true)
  2014. // window.addEventListener('yt-update-c3-companion', (evt) => {
  2015. // console.log(evt.type)
  2016. // }, true)
  2017. // window.addEventListener('video-progress', (evt) => {
  2018. // // console.log(evt.type)
  2019. // }, true)
  2020. // window.addEventListener('localmediachange', (evt) => {
  2021. // console.log(evt.type)
  2022. // }, true)
  2023.  
  2024.  
  2025.  
  2026. // document.addEventListener('player-error', (evt) => {
  2027. // console.log(3001, evt.type, evt)
  2028. // }, true)
  2029. // document.addEventListener('player-detailed-error', (evt) => {
  2030. // console.log(3002, evt.type, evt)
  2031. // }, true)
  2032.  
  2033.  
  2034.  
  2035. async function delayRun(pr) {
  2036.  
  2037. let q = document.querySelector('#movie_player');
  2038. if (!q) return;
  2039. let a = document.querySelector('.video-stream.html5-main-video');
  2040. if (!a) return;
  2041.  
  2042. await pr.then();
  2043.  
  2044. if (fa !== 1) {
  2045. return;
  2046. } else if (a.muted === true) {
  2047. return;
  2048. } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) {
  2049. if (a.paused === false) return;
  2050. } else {
  2051. return;
  2052. }
  2053.  
  2054. if (document.querySelector('.player-controls-content')) return;
  2055.  
  2056. if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) {
  2057.  
  2058. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  2059.  
  2060. }
  2061.  
  2062. if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) {
  2063.  
  2064. if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead();
  2065. if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) {
  2066. if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime();
  2067. }
  2068. }
  2069.  
  2070. }
  2071.  
  2072. durationchangeForMobile = true;
  2073.  
  2074. }
  2075.  
  2076. attachOneTimeEvent('yt-action', function () {
  2077. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  2078. ytConfigFix(config_);
  2079. });
  2080.  
  2081. let prepared = false;
  2082. function prepare() {
  2083. if (prepared) return;
  2084. prepared = true;
  2085.  
  2086. if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') {
  2087.  
  2088. for (const [k, v] of Object.entries(_yt_player)) {
  2089.  
  2090. const p = typeof v === 'function' ? v.prototype : 0;
  2091.  
  2092. if (p
  2093. && typeof p.clone === 'function'
  2094. && typeof p.get === 'function' && typeof p.set === 'function'
  2095. && typeof p.isEmpty === 'undefined' && typeof p.forEach === 'undefined'
  2096. && typeof p.clear === 'undefined'
  2097. ) {
  2098.  
  2099. key = k;
  2100.  
  2101. }
  2102.  
  2103. }
  2104.  
  2105. }
  2106.  
  2107. if (key) {
  2108.  
  2109. const ClassX = _yt_player[key];
  2110. _yt_player[key] = class extends ClassX {
  2111. constructor(...args) {
  2112.  
  2113. if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = '';
  2114. super(...args);
  2115.  
  2116. }
  2117. }
  2118. _yt_player[key].luX1Y = 1;
  2119. prototypeInherit(_yt_player[key].prototype, ClassX.prototype);
  2120. }
  2121.  
  2122. }
  2123. let s3 = Symbol();
  2124.  
  2125. generalRegister('deviceIsAudioOnly', s3, (p) => {
  2126. return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p)
  2127. }, {
  2128.  
  2129. get() {
  2130. return this[s3];
  2131. },
  2132. set(nv) {
  2133. if (typeof nv === 'boolean') this[s3] = true;
  2134. else this[s3] = undefined;
  2135. prepare();
  2136. return true;
  2137. },
  2138. enumerable: false,
  2139. configurable: true
  2140.  
  2141. });
  2142.  
  2143.  
  2144. let s1 = Symbol();
  2145. let s2 = Symbol();
  2146. Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', {
  2147. get() {
  2148. // console.log(501, this.constructor.prototype)
  2149. return undefined;
  2150. },
  2151. set(nv) {
  2152. return true;
  2153. },
  2154. enumerable: false,
  2155. configurable: true
  2156. });
  2157.  
  2158. Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', {
  2159. get() {
  2160. // console.log(502, this.constructor.prototype)
  2161. return this[s1];
  2162. },
  2163. set(nv) {
  2164. if (typeof nv === 'boolean') this[s1] = false;
  2165. else this[s1] = undefined;
  2166. return true;
  2167. },
  2168. enumerable: false,
  2169. configurable: true
  2170. });
  2171.  
  2172. Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', {
  2173. get() {
  2174. // console.log(503, this.constructor.prototype)
  2175. return this[s2];
  2176. },
  2177. set(nv) {
  2178. if (typeof nv === 'boolean') this[s2] = false;
  2179. else this[s2] = undefined;
  2180. return true;
  2181. },
  2182. enumerable: false,
  2183. configurable: true
  2184. });
  2185.  
  2186.  
  2187. const supportedFormatsConfig = () => {
  2188.  
  2189. function typeTest(type) {
  2190. if (typeof type === 'string' && type.startsWith('video/')) {
  2191. return false;
  2192. }
  2193. }
  2194.  
  2195. // return a custom MIME type checker that can defer to the original function
  2196. function makeModifiedTypeChecker(origChecker) {
  2197. // Check if a video type is allowed
  2198. return function (type) {
  2199. let res = undefined;
  2200. if (type === undefined) res = false;
  2201. else {
  2202. res = typeTest.call(this, type);
  2203. }
  2204. if (res === undefined) res = origChecker.apply(this, arguments);
  2205. return res;
  2206. };
  2207. }
  2208.  
  2209. // Override video element canPlayType() function
  2210. const proto = (HTMLVideoElement || 0).prototype;
  2211. if (proto && typeof proto.canPlayType == 'function') {
  2212. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  2213. }
  2214.  
  2215. // Override media source extension isTypeSupported() function
  2216. const mse = window.MediaSource;
  2217. // Check for MSE support before use
  2218. if (mse && typeof mse.isTypeSupported == 'function') {
  2219. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  2220. }
  2221.  
  2222. };
  2223.  
  2224. supportedFormatsConfig();
  2225.  
  2226.  
  2227. PATCH_MEDIA_PUBLISH && (async ()=>{
  2228.  
  2229.  
  2230. const _yt_player_observable = observablePromise(() => {
  2231. return (((window || 0)._yt_player || 0) || 0);
  2232. });
  2233.  
  2234. const addProtoToArr = (parent, key, arr) => {
  2235.  
  2236.  
  2237. let isChildProto = false;
  2238. for (const sr of arr) {
  2239. if (parent[key].prototype instanceof parent[sr]) {
  2240. isChildProto = true;
  2241. break;
  2242. }
  2243. }
  2244.  
  2245. if (isChildProto) return;
  2246.  
  2247. arr = arr.filter(sr => {
  2248. if (parent[sr].prototype instanceof parent[key]) {
  2249. return false;
  2250. }
  2251. return true;
  2252. });
  2253.  
  2254. arr.push(key);
  2255.  
  2256. return arr;
  2257.  
  2258.  
  2259. };
  2260. /*
  2261.  
  2262. const getD0 = (_yt_player) => {
  2263.  
  2264. const w = 'D0';
  2265.  
  2266. let arr = [];
  2267.  
  2268. for (const [k, v] of Object.entries(_yt_player)) {
  2269.  
  2270. const p = typeof v === 'function' ? v.prototype : 0;
  2271. if (p
  2272. && typeof p.playVideo === 'function' && p.playVideo.length === 1
  2273. && typeof p.getVisibilityState === 'function' && p.getVisibilityState.length === 8
  2274. && typeof p.getVideoData === 'function' && p.getVideoData.length === 0
  2275. && typeof p.seekTo === 'function' && p.seekTo.length === 5
  2276. && typeof p.pauseVideo === 'function' && p.pauseVideo.length === 2
  2277. && typeof p.stopVideo === 'function' && p.stopVideo.length === 1
  2278. && typeof p.getPresentingPlayerType === 'function' && p.getPresentingPlayerType.length === 1
  2279. && typeof p.getCurrentTime === 'function' && p.getCurrentTime.length === 3
  2280. && typeof p.cancelPlayback === 'function' && p.cancelPlayback.length === 2
  2281. // && !p.getPlayerType
  2282.  
  2283. ) {
  2284. arr = addProtoToArr(_yt_player, k, arr) || arr;
  2285.  
  2286.  
  2287. }
  2288.  
  2289. }
  2290.  
  2291. if (arr.length === 0) {
  2292.  
  2293. console.warn(`Key does not exist. [${w}]`);
  2294. } else {
  2295.  
  2296. console.log(`[${w}]`, arr);
  2297. return arr[0];
  2298. }
  2299.  
  2300. }
  2301. */
  2302.  
  2303. const gets0 = (_yt_player) => {
  2304.  
  2305. const w = 's0';
  2306.  
  2307. let arr = [];
  2308.  
  2309. for (const [k, v] of Object.entries(_yt_player)) {
  2310.  
  2311. const p = typeof v === 'function' ? v.prototype : 0;
  2312. if (p
  2313. && typeof p.isBackground === 'function' && p.isBackground.length === 0
  2314. && typeof p.getPlaybackRate === 'function' && p.getPlaybackRate.length === 0
  2315. && typeof p.publish === 'function' && p.publish.length === 2
  2316. && typeof p.isAtLiveHead === 'function' && p.isAtLiveHead.length === 2
  2317.  
  2318.  
  2319.  
  2320. // && !p.getPlayerType
  2321.  
  2322. ) {
  2323. arr = addProtoToArr(_yt_player, k, arr) || arr;
  2324.  
  2325.  
  2326. }
  2327.  
  2328. }
  2329.  
  2330. if (arr.length === 0) {
  2331.  
  2332. console.warn(`Key does not exist. [${w}]`);
  2333. } else {
  2334.  
  2335. console.log(`[${w}]`, arr);
  2336. return arr[0];
  2337. }
  2338.  
  2339. };
  2340.  
  2341. const printObject = (b)=>{
  2342. return JSON.stringify( Object.entries(b||{}).filter(e=>typeof (e[1]||0)!=='object'));
  2343. };
  2344.  
  2345. /*
  2346. (async () => {
  2347. // rAf scheduling
  2348. const _yt_player = await _yt_player_observable.obtain();
  2349. if (!_yt_player || typeof _yt_player !== 'object') return;
  2350. let keyD0 = getD0(_yt_player);
  2351. if (!keyD0) return;
  2352. const g = _yt_player
  2353. let k = keyD0
  2354. const gk = g[k];
  2355. if (typeof gk !== 'function') return;
  2356. const gkp = gk.prototype;
  2357.  
  2358.  
  2359. gkp.playVideo48 = gkp.playVideo;
  2360. gkp.playVideo = function(a) {
  2361. let r = this.playVideo48(a);
  2362. // console.log('gkpD0 playVideo',r, a)
  2363. return r;
  2364. }
  2365.  
  2366. gkp.getVisibilityState48 = gkp.getVisibilityState;
  2367. gkp.getVisibilityState = function(a, b, c, d, e, f, h, l) {
  2368. let r = this.getVisibilityState48(a, b, c, d, e, f, h, l);
  2369. // console.log('gkpD0 getVisibilityState',r, a,b,c,d,e,f,h,l)
  2370. r = 0;
  2371. return r;
  2372. }
  2373.  
  2374.  
  2375. gkp.getVideoData48 = gkp.getVideoData;
  2376. gkp.getVideoData = function() {
  2377. let r = this.getVideoData48();
  2378. // console.log('gkpD0 getVideoData',r)
  2379. return r;
  2380. }
  2381.  
  2382. gkp.seekTo48 = gkp.seekTo;
  2383. gkp.seekTo = function(a, b, c, d, e) {
  2384. let r = this.seekTo48(a, b, c, d, e);
  2385. // console.log('gkpD0 seekTo',r, a,b,c,d,e)
  2386. return r;
  2387. }
  2388.  
  2389. gkp.pauseVideo48 = gkp.pauseVideo;
  2390. gkp.pauseVideo = function(a, b) {
  2391. let r = this.pauseVideo48(a, b);
  2392. // console.log('gkpD0 pauseVideo',r, a,b);
  2393. return r;
  2394. }
  2395.  
  2396.  
  2397. gkp.stopVideo48 = gkp.stopVideo;
  2398. gkp.stopVideo = function(a) {
  2399. let r = this.stopVideo48(a);
  2400. // console.log('gkpD0 stopVideo',r,a)
  2401. return r;
  2402. }
  2403.  
  2404.  
  2405.  
  2406.  
  2407. gkp.getPresentingPlayerType48 = gkp.getPresentingPlayerType;
  2408. gkp.getPresentingPlayerType = function(a) {
  2409. let r = this.getPresentingPlayerType48(a);
  2410. // console.log('gkpD0 getPresentingPlayerType',r,a)
  2411. return r;
  2412. }
  2413.  
  2414. gkp.getCurrentTime48 = gkp.getCurrentTime;
  2415. gkp.getCurrentTime = function(a, b, c) {
  2416. let r = this.getCurrentTime48(a, b, c);
  2417. // console.log('gkpD0 getCurrentTime',r, a,b,c)
  2418. return r;
  2419. }
  2420.  
  2421. gkp.cancelPlayback48 = gkp.cancelPlayback;
  2422. gkp.cancelPlayback = function(a, b) {
  2423. let r = this.cancelPlayback48(a, b);
  2424. // console.log('gkpD0 cancelPlayback',r, a,b);
  2425. return r;
  2426. }
  2427. })();
  2428. */
  2429.  
  2430.  
  2431.  
  2432. /**
  2433. *
  2434. *
  2435.  
  2436. g.k.mL = function(a) {
  2437. var b = a.target.Gf();
  2438. if (this.mediaElement && this.mediaElement.Gf() && this.mediaElement.Gf() === b) {
  2439. ehb(this, a.type);
  2440. switch (a.type) {
  2441. case "error":
  2442. var c = yFa(this.mediaElement) || ""
  2443. , d = this.mediaElement.xf();
  2444. if (c === "capability.changed") {
  2445. this.L("html5_restart_on_capability_change") ? (this.ma("capchg", {
  2446. msg: d
  2447. }),
  2448. F_(this, !0)) : u0(this);
  2449. return
  2450. }
  2451. if (this.mediaElement.hasError() && (Ndb(this.al, c, {
  2452. msg: d
  2453. }) || g.zS(this.videoData) && this.wb && this.wb.handleError(c)))
  2454. return;
  2455. if (this.isBackground() && this.mediaElement.fh() === 4) {
  2456. this.So();
  2457. x0(this, "unplayable");
  2458. return
  2459. }
  2460. break;
  2461. case "durationchange":
  2462. c = this.mediaElement.getDuration();
  2463. isFinite(c) && (!this.Qa || c > 0) && c !== 1 && this.Hl(c);
  2464. break;
  2465. case "ratechange":
  2466. this.ya && this.ya.setPlaybackRate(this.mediaElement.getPlaybackRate());
  2467. xfb(this.Ch);
  2468. this.wc().onPlaybackRateChange(this.getPlaybackRate());
  2469. break;
  2470. case "loadedmetadata":
  2471. ghb(this);
  2472. this.publish("onLoadedMetadata");
  2473. W5a(this);
  2474. c = this.bf();
  2475. this.videoData.SB && (this.videoData.SB = c);
  2476. break;
  2477. case "loadstart":
  2478. W5a(this);
  2479. break;
  2480. case "progress":
  2481. case "suspend":
  2482. this.Uc();
  2483. this.publish("onLoadProgress", this, this.Sw());
  2484. break;
  2485. case "playing":
  2486. this.Rb.uv("plev");
  2487. this.bT && !k0(this) && (this.bT = !1,
  2488. this.isAtLiveHead() || (this.logger.debug("seek to infinity on PLAYING"),
  2489. this.seekTo(Infinity, {
  2490. kd: "videoplayer_onPlaying"
  2491. })));
  2492. break;
  2493. case "timeupdate":
  2494. c = this.mediaElement && !this.mediaElement.getCurrentTime();
  2495. d = this.mediaElement && this.mediaElement.Tk() === 0;
  2496. if (c && (!this.VK || d))
  2497. return;
  2498. this.VK = this.VK || !!this.mediaElement.getCurrentTime();
  2499. Vgb(this);
  2500. this.Uc();
  2501. if (!this.mediaElement || this.mediaElement.Gf() !== b)
  2502. return;
  2503. this.publish("onVideoProgress", this, this.getCurrentTime());
  2504. break;
  2505. case "waiting":
  2506. if (this.mediaElement.Vw().length > 0 && this.mediaElement.Eh().length === 0 && this.mediaElement.getCurrentTime() > 0 && this.mediaElement.getCurrentTime() < 5 && this.ya)
  2507. return;
  2508. 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(),
  2509. c.bh = sK(this.mediaElement).toFixed(3),
  2510. this.ma("uwe", c));
  2511. g.zS(this.videoData) && this.wb && n7a(this.wb, this.mediaElement.getCurrentTime());
  2512. break;
  2513. case "resize":
  2514. ghb(this);
  2515. this.videoData.B && this.videoData.B.video.quality === "auto" && this.publish("internalvideoformatchange", this.videoData, !1);
  2516. break;
  2517. case "pause":
  2518. if (this.TW && g.pF(this.playerState, 8) && !g.pF(this.playerState, 1024) && this.getCurrentTime() === 0 && g.VB) {
  2519. x0(this, "safari_autoplay_disabled");
  2520. return
  2521. }
  2522. }
  2523. if (this.mediaElement && this.mediaElement.Gf() === b) {
  2524. dgb(this.Tc, a, this.wb || void 0);
  2525. this.publish("videoelementevent", a);
  2526. b = this.playerState;
  2527. d = this.bE;
  2528. var e = this.mediaElement;
  2529. c = this.videoData.clientPlaybackNonce;
  2530. var f = g.zS(this.videoData) && this.wb ? jY(this.wb) : void 0;
  2531. if (!g.pF(b, 128)) {
  2532. var h = b.state;
  2533. e = e ? e : a.target;
  2534. var l = e.getCurrentTime();
  2535. if (!g.pF(b, 64) || a.type !== "ended" && a.type !== "pause") {
  2536. f = f || e.getDuration();
  2537. f = e.isEnded() || l > 1 && Math.abs(l - f) < 1.1;
  2538. var m = a.type === "pause" && e.isEnded();
  2539. l = a.type === "ended" || a.type === "waiting" || a.type === "timeupdate" && !g.pF(b, 4) && !a0(d, l);
  2540. if (m || f && l)
  2541. e.KJ() > 0 && e.Gf() && (h = 14);
  2542. else
  2543. switch (a.type) {
  2544. case "error":
  2545. yFa(e) && (h |= 128);
  2546. break;
  2547. case "pause":
  2548. g.pF(b, 256) ? (h ^= 256) || (h = 64) : g.pF(b, 32) || g.pF(b, 2) || g.pF(b, 4) || (h = 4,
  2549. g.pF(b, 1) && g.pF(b, 8) && (h |= 1));
  2550. break;
  2551. case "playing":
  2552. l = h;
  2553. h = (h | 8) & -1093;
  2554. l & 4 ? (h |= 1,
  2555. uK(d, e)) : a0(d, e.getCurrentTime()) && (h &= -2);
  2556. g.pF(b, 1) && uK(d, e) && (h |= 1);
  2557. break;
  2558. case "seeking":
  2559. h |= 16;
  2560. g.pF(b, 8) && (h |= 1);
  2561. h &= -3;
  2562. break;
  2563. case "seeked":
  2564. h &= -17;
  2565. uK(d, e);
  2566. break;
  2567. case "waiting":
  2568. g.pF(b, 2) || (h |= 1);
  2569. uK(d, e);
  2570. break;
  2571. case "timeupdate":
  2572. l = g.pF(b, 16),
  2573. f = g.pF(b, 4),
  2574. (g.pF(b, 8) || l) && !f && a0(d, e.getCurrentTime()) && (h = 8),
  2575. uK(d, e) && (h |= 1)
  2576. }
  2577. }
  2578. d = h;
  2579. h = null;
  2580. d & 128 && (h = a.target,
  2581. e = yFa(h),
  2582. l = 1,
  2583. e ? (e === "capability.changed" && (l = 2),
  2584. f = "GENERIC_WITHOUT_LINK",
  2585. m = h.uc(),
  2586. m.mediaElem = "1",
  2587. /AUDIO_RENDERER/.test(h.xf()) && (f = "HTML5_AUDIO_RENDERER_ERROR"),
  2588. h = {
  2589. errorCode: e,
  2590. errorMessage: g.JV[f] || "",
  2591. bP: f,
  2592. KL: yJ(m),
  2593. rJ: l,
  2594. cpn: b.Pg ? b.Pg.cpn : ""
  2595. }) : h = null,
  2596. h && (h.cpn = c));
  2597. b = vK(b, d, h)
  2598. }
  2599. !g.pF(this.playerState, 1) && g.pF(b, 1) && dhb(this, "evt" + a.type);
  2600. this.Ic(b)
  2601. }
  2602. }
  2603. }
  2604. ;
  2605. *
  2606. *
  2607. */
  2608.  
  2609.  
  2610.  
  2611.  
  2612. (async () => {
  2613. // rAf scheduling
  2614. const _yt_player = await _yt_player_observable.obtain();
  2615. if (!_yt_player || typeof _yt_player !== 'object') return;
  2616. let keys0 = gets0(_yt_player);
  2617. if (!keys0) return;
  2618. const g = _yt_player
  2619. let k = keys0
  2620. const gk = g[k];
  2621. if (typeof gk !== 'function') return;
  2622. const gkp = gk.prototype;
  2623.  
  2624.  
  2625. // gkp.isBackground48 = gkp.isBackground;
  2626. // gkp.isBackground = function() {
  2627. // if(!this?.visibility?.isBackground88){
  2628. // this.visibility.isBackground88 = 1;
  2629. // this.visibility.isBackground = function(){
  2630. // return false;
  2631. // }
  2632. // }
  2633. // // console.log('gkps0', 'isBackground', this.visibility)
  2634. // // return false;
  2635. // // if(!this.mediaElement || !(this.mediaElement.readyState>=4)){
  2636. // // return false;
  2637. // // }
  2638. // // console.log(1882,)
  2639. // return this.isBackground48();
  2640. // }
  2641.  
  2642. gkp.publish48 = gkp.publish;
  2643. gkp.publish33 = async function(a,b){
  2644.  
  2645. const player_ = kRef(globalPlayer);
  2646. let publishStatus = 0;
  2647. const media = this.mediaElement;
  2648.  
  2649. if(a==='internalaudioformatchange' && typeof (b.author||0) === 'string' && media){
  2650.  
  2651. await player_.clearVideo(); // avoid error in live streaming
  2652. await player_.clearQueue(); // avoid error in live streaming
  2653. await refreshAllStaleEntitiesForNonReadyAudio();
  2654. // await player_.cancelPlayback();
  2655. publishStatus = media.__publishStatus17__ = 100;
  2656. }
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662. const domMedia = media ? Object.values(media).filter(e => e instanceof HTMLMediaElement) : [];
  2663. if (this.mediaElement && a !== 'internalvideoformatchange' && player_ && domMedia.length === 1) {
  2664.  
  2665. const audio = domMedia[0];
  2666.  
  2667.  
  2668.  
  2669. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  2670. try {
  2671. if (audio.readyState == 0 && audio.isConnected === true) await player_.refreshAllStaleEntities();
  2672. } catch (e) {
  2673. }
  2674. };
  2675. // const triggerPlaying = async () => {
  2676. // await player_.cancelPlayback();
  2677. // this.pauseVideo();
  2678. // this.playVideo();
  2679. // await player_.pauseVideo();
  2680. // await player_.playVideo();
  2681. // };
  2682. const seekToLiveHeadForLiveStream = async () => {
  2683. try {
  2684. audio.isConnected === true && await player_.seekToLiveHead();
  2685. if (audio.isConnected === true && (await player_.isAtLiveHead()) === true) {
  2686. audio.isConnected === true && await player_.seekToStreamTime();
  2687. return true;
  2688. }
  2689. } catch (e) {
  2690. console.log('error_F7', e);
  2691. }
  2692. };
  2693.  
  2694.  
  2695. if(a.includes('error') ){
  2696. if(!media.__publishStatus17__ || media.__publishStatus17__ < 200){
  2697.  
  2698. await player_.clearVideo(); // avoid error in live streaming
  2699. await player_.clearQueue(); // avoid error in live streaming
  2700. await refreshAllStaleEntitiesForNonReadyAudio();
  2701. // await player_.cancelPlayback();
  2702.  
  2703. }
  2704. }else{
  2705.  
  2706.  
  2707.  
  2708. media.__publishStatus17__ = media.__publishStatus17__ || 100;
  2709.  
  2710.  
  2711.  
  2712. if (media.__publishStatus17__ === 100) await refreshAllStaleEntitiesForNonReadyAudio();
  2713. if (media.__publishStatus17__ === 100 && audio.duration > 0 && player_.getPlayerState() === 3) {
  2714. media.__publishStatus17__ = 200
  2715. // await refreshAllStaleEntitiesForNonReadyAudio();
  2716. await player_.cancelPlayback();
  2717. await this.pauseVideo();
  2718. // this.playVideo();
  2719. // await player_.pauseVideo();
  2720. await player_.playVideo();
  2721. await seekToLiveHeadForLiveStream();
  2722. // fixLiveAudioFn(domMedia0, player_, player_.getPlayerState())
  2723. // skipPause = true;
  2724. // skipVisibility = true;
  2725. // player_.cancelPlayback();
  2726. // player_.pauseVideo();
  2727. // player_.playVideo();
  2728. // skipPause = false;
  2729. // skipVisibility = false;
  2730. }
  2731. if (a === 'onLoadedMetadata' && media.__publishStatus17__ === 200) media.__publishStatus17__ = 201;
  2732. if (a === 'videoelementevent' && b.type === 'loadedmetadata' && media.__publishStatus17__ === 201) media.__publishStatus17__ = 202;
  2733. if (a === 'videoelementevent' && b.type === 'progress' && media.__publishStatus17__ === 202) {
  2734. media.__publishStatus17__ = 203;
  2735. window.debug_mfk = this;
  2736. window.debug_mfp = player_;
  2737. // (async ()=>{
  2738. // await timelineResolve();
  2739. // const domMedia = Object.values(this.mediaElement).filter(e=>e instanceof HTMLMediaElement);
  2740. // if(domMedia.length === 1){
  2741. // const domMedia0 = domMedia[0]
  2742. // if(domMedia0.duration >0 && domMedia0.readyState >= 4){
  2743. // await timelineResolve();
  2744. // console.log(939, domMedia0, domMedia0.paused, domMedia0.duration, domMedia0.readyState)
  2745. // this.pauseVideo();
  2746. // await timelineResolve();
  2747. // this.playVideo();
  2748. // }
  2749. // // this.mediaElement.pause();
  2750. // // this.mediaElement.play();
  2751. // }
  2752. // })();
  2753. }
  2754. if (media.__publishStatus17__ === 203 && audio && audio.readyState === 1) {
  2755. media.__publishStatus17__ = 204;
  2756. // await timelineResolve();
  2757. // await player_.cancelPlayback();
  2758. await this.pauseVideo();
  2759. // this.playVideo();
  2760. // await timelineResolve();
  2761. // await player_.pauseVideo();
  2762. await player_.playVideo();
  2763. // await timelineResolve();
  2764. await seekToLiveHeadForLiveStream();
  2765. }
  2766. if (media.__publishStatus17__ < 300 && media.__publishStatus17__ >= 200 && a === 'videoelementevent' && b.type==='timeupdate' && !audio.paused && audio.readyState >= 4 && audio.duration > 0) {
  2767. media.__publishStatus17__ = 300;
  2768. if(!player_.isAtLiveHead()) await seekToLiveHeadForLiveStream();
  2769. }
  2770.  
  2771. }
  2772.  
  2773.  
  2774. publishStatus = media.__publishStatus17__;
  2775.  
  2776. if (debugFlg001) console.log('gkps0 publish | ' + publishStatus, a, printObject(b))
  2777.  
  2778. }
  2779. }
  2780. gkp.publish = function(a,b){
  2781.  
  2782. this.publish33(a,b);
  2783. return this.publish48.apply(this, arguments);
  2784. }
  2785.  
  2786. // console.log(23488)
  2787.  
  2788. })();
  2789.  
  2790. })();
  2791.  
  2792.  
  2793. }
  2794.  
  2795. const getVideoIdByURL = () => {
  2796. // It's almost certainly going to stay at 11 characters. The individual characters come from a set of 64 possibilities (A-Za-z0-9_-).
  2797. // base64 form; 26+26+10+2; 64^len
  2798. // Math.pow(64,11) = 73786976294838210000
  2799.  
  2800. const url = new URL(location.href);
  2801. let m;
  2802.  
  2803. if (m = /^\/watch\?v=([A-Za-z0-9_-]+)/.exec(url.pathname + url.search)) return `${m[1]}`;
  2804. if (m = /^\/live\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`;
  2805.  
  2806. if (m = /^\/embed\/live_stream\?channel=([A-Za-z0-9_-]+)/.exec(url.pathname + url.search)) return `L:${m[1]}`;
  2807. if (m = /^\/embed\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`;
  2808.  
  2809. if (m = /^\/channel\/([A-Za-z0-9_-]+)\/live\b/.exec(url.pathname)) return `L:${m[1]}`;
  2810. if (url.hostname === 'youtu.be' && (m = /\/([A-Za-z0-9_-]+)/.exec(url.pathname))) return `${m[1]}`;
  2811.  
  2812. return '';
  2813.  
  2814. };
  2815.  
  2816. const getVideoIdByElement = ()=>{
  2817. const videoIdElements = [...document.querySelectorAll('[video-id]')].filter(v => !v.closest('[hidden]'));
  2818. const videoId = videoIdElements.length > 0 ? videoIdElements[0].getAttribute('video-id') : null;
  2819. return videoId || '';
  2820. };
  2821.  
  2822. const getEnableValue = async ()=>{
  2823. const videoId = getVideoIdByURL() || getVideoIdByElement();
  2824. const siteVal = videoId ? await GM.getValue(`isEnable_aWsjF_${videoId}`, null) : null;
  2825. return (siteVal !== null) ? siteVal : await GM.getValue("isEnable_aWsjF", true);
  2826. };
  2827.  
  2828. const setEnableVal = async (val)=>{
  2829. const videoId = getVideoIdByURL() || getVideoIdByElement();
  2830. if (videoId) {
  2831. try {
  2832. const cv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null);
  2833. if (typeof cv === typeof val) await GM.setValue(`isEnable_aWsjF_${videoId}`, val);
  2834. } catch (e) { }
  2835. }
  2836. await GM.setValue("isEnable_aWsjF", val);
  2837. }
  2838.  
  2839. const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? await getEnableValue() : null;
  2840. if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
  2841. if (isEnable) {
  2842. const element = document.createElement('button');
  2843. element.setAttribute('onclick', createHTML(`(${pageInjectionCode})()`));
  2844. element.click();
  2845. }
  2846.  
  2847. GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
  2848. await setEnableVal(!isEnable);
  2849. await GM.setValue('lastCheck_bWsm5', Date.now());
  2850. document.documentElement.setAttribute('forceRefresh032', '');
  2851. location.reload();
  2852. });
  2853.  
  2854. let messageCount = 0;
  2855. let busy = false;
  2856. window.addEventListener('message', (evt) => {
  2857.  
  2858. const v = ((evt || 0).data || 0).ZECxh;
  2859. if (typeof v === 'boolean') {
  2860. if (messageCount > 1e9) messageCount = 9;
  2861. const t = ++messageCount;
  2862. if (v && isEnable) {
  2863. requestAnimationFrame(async () => {
  2864. if (t !== messageCount) return;
  2865. if (busy) return;
  2866. busy = true;
  2867. if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
  2868. await setEnableVal(!isEnable);
  2869. await GM.setValue('lastCheck_bWsm5', Date.now());
  2870. document.documentElement.setAttribute('forceRefresh032', '');
  2871. location.reload();
  2872. }
  2873. busy = false;
  2874. });
  2875. }
  2876. }
  2877.  
  2878. });
  2879.  
  2880.  
  2881. const pLoad = new Promise(resolve => {
  2882. if (document.readyState !== 'loading') {
  2883. resolve();
  2884. } else {
  2885. window.addEventListener("DOMContentLoaded", resolve, false);
  2886. }
  2887. });
  2888.  
  2889.  
  2890. function contextmenuInfoItemAppearedFn(target) {
  2891.  
  2892. const btn = target.closest('.ytp-menuitem[role="menuitem"]');
  2893. if (!btn) return;
  2894. if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return;
  2895. document.documentElement.classList.add('with-audio-only-toggle-btn');
  2896. const newBtn = btn.cloneNode(true)
  2897. newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  2898. newBtn.classList.add('audio-only-toggle-btn');
  2899. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  2900. newBtn.addEventListener('click', async () => {
  2901. await setEnableVal(!isEnable);
  2902. await GM.setValue('lastCheck_bWsm5', Date.now());
  2903. document.documentElement.setAttribute('forceRefresh032', '');
  2904. location.reload();
  2905. });
  2906. let t;
  2907. let h = 0;
  2908. t = btn.closest('.ytp-panel-menu[style*="height"]');
  2909. if (t) t.style.height = t.scrollHeight + 'px';
  2910. t = btn.closest('.ytp-panel[style*="height"]');
  2911. if (t) t.style.height = (h = t.scrollHeight) + 'px';
  2912. t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]');
  2913. if (t && h > 0) t.style.height = h + 'px';
  2914. }
  2915.  
  2916.  
  2917. function mobileMenuItemAppearedFn(target) {
  2918.  
  2919. const btn = target.closest('ytm-menu-item');
  2920. if (!btn) return;
  2921. if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return;
  2922. document.documentElement.classList.add('with-audio-only-toggle-btn');
  2923. const newBtn = btn.cloneNode(true);
  2924. newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  2925. newBtn.classList.add('audio-only-toggle-btn');
  2926. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  2927. newBtn.addEventListener('click', async () => {
  2928. await setEnableVal(!isEnable);
  2929. await GM.setValue('lastCheck_bWsm5', Date.now());
  2930. document.documentElement.setAttribute('forceRefresh032', '');
  2931. location.reload();
  2932. });
  2933. }
  2934.  
  2935. pLoad.then(() => {
  2936.  
  2937. document.addEventListener('animationstart', (evt) => {
  2938. const animationName = evt.animationName;
  2939. if (!animationName) return;
  2940.  
  2941. if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target);
  2942. if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target);
  2943.  
  2944. }, true);
  2945.  
  2946. const cssForEnabled = isEnable ? `
  2947.  
  2948. .html5-video-player {
  2949. background-color: black;
  2950. }
  2951.  
  2952. [style*="--audio-only-thumbnail-image"]{
  2953. background-image: var(--audio-only-thumbnail-image);
  2954. object-fit: contain;
  2955. background-position: center;
  2956. background-size: contain;
  2957. background-repeat: no-repeat;
  2958. }
  2959. .html5-video-player.ended-mode [style*="--audio-only-thumbnail-image"]{
  2960. background-image: none;
  2961. }
  2962.  
  2963. .html5-video-player.ytp-ce-shown .html5-video-container {
  2964. opacity: 0.5;
  2965. transition: opacity 0.5s;
  2966. }
  2967.  
  2968. ytd-video-preview #media-container div#player-container,
  2969. ytd-video-preview #media-container div#thumbnail-container{
  2970. transition: initial !important;
  2971. transition-duration:0ms !important;
  2972. transition-delay:0ms !important;
  2973. }
  2974. ytd-video-preview #media-container div#thumbnail-container{
  2975. /* pointer-events:none !important; */
  2976. opacity:0;
  2977. /* z-index:-1; */
  2978. }
  2979. ytd-video-preview #media-container div#player-container,
  2980. ytd-video-preview #media-container div#inline-preview-player{
  2981. background-color:transparent !important;
  2982. background-image:none !important;
  2983. }
  2984.  
  2985. #movie_player > .html5-video-container:not(:empty) {
  2986. box-sizing: border-box;
  2987. height: 100%;
  2988. }
  2989.  
  2990. #movie_player [style*="--audio-only-thumbnail-image"] ~ .ytp-cued-thumbnail-overlay > .ytp-cued-thumbnail-overlay-image[style*="background-image"] {
  2991. opacity: 0;
  2992. }
  2993.  
  2994. #movie_player [style*="--audio-only-thumbnail-image"]::before {
  2995. content: '';
  2996. display: block;
  2997. position: absolute;
  2998. left: 0;
  2999. top: 0;
  3000. bottom: 0;
  3001. right: 0;
  3002. /* background: transparent; */
  3003.  
  3004.  
  3005. /* We use multiple backgrounds: one gradient per side */
  3006. background:
  3007. /* Left border gradient */
  3008. linear-gradient(to right, rgba(0,0,0,0.4), transparent) left center,
  3009. /* Right border gradient */
  3010. linear-gradient(to left, rgba(0,0,0,0.4), transparent) right center,
  3011. /* Top border gradient */
  3012. linear-gradient(to bottom, rgba(0,0,0,0.4), transparent) center top,
  3013. /* Bottom border gradient */
  3014. linear-gradient(to top, rgba(0,0,0,0.4), transparent) center bottom;
  3015. /* Prevents repetition of gradients */
  3016. background-repeat: no-repeat;
  3017. /* Set the size of each gradient "border" */
  3018. background-size:
  3019. 12% 100%, /* left border width and full height */
  3020. 12% 100%, /* right border width and full height */
  3021. 100% 12%, /* top border full width and small height */
  3022. 100% 12%; /* bottom border full width and small height */
  3023. /* Optional: a base background color inside the element */
  3024. /* background-color: #fff; */
  3025. /* background-color: var(--blinker-fmw83-bgc, transparent); */
  3026.  
  3027. opacity: var(--fmw83-opacity, 1);
  3028.  
  3029. pointer-events: none !important;
  3030. z-index:-1;
  3031.  
  3032. }
  3033.  
  3034. /*
  3035. @keyframes blinker-fmw83 {
  3036. 0%, 60%, 100% {
  3037. opacity: 1;
  3038. }
  3039. 30% {
  3040. opacity: 0.96;
  3041. }
  3042. }
  3043. */
  3044. #movie_player.playing-mode [style*="--audio-only-thumbnail-image"]{
  3045. /* animation: blinker-fmw83 1.74s linear infinite; */
  3046. --fmw83-opacity: 0.6;
  3047. }
  3048.  
  3049.  
  3050. `: "";
  3051.  
  3052. const style = document.createElement('style');
  3053. style.id = 'fm9v0';
  3054. style.textContent = `
  3055.  
  3056. ${cssForEnabled}
  3057.  
  3058. @keyframes mobileMenuItemAppeared {
  3059. 0% {
  3060. background-position-x: 3px;
  3061. }
  3062. 100% {
  3063. background-position-x: 4px;
  3064. }
  3065. }
  3066. ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type {
  3067. animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards;
  3068. }
  3069. @keyframes contextmenuInfoItemAppeared {
  3070. 0% {
  3071. background-position-x: 3px;
  3072. }
  3073. 100% {
  3074. background-position-x: 4px;
  3075. }
  3076. }
  3077. .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{
  3078. animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards;
  3079. }
  3080. #confirmDialog794 {
  3081. z-index:999999 !important;
  3082. display: none;
  3083. /* Hidden by default */
  3084. position: fixed;
  3085. /* Stay in place */
  3086. z-index: 1;
  3087. /* Sit on top */
  3088. left: 0;
  3089. top: 0;
  3090. width: 100%;
  3091. /* Full width */
  3092. height: 100%;
  3093. /* Full height */
  3094. overflow: auto;
  3095. /* Enable scroll if needed */
  3096. background-color: rgba(0,0,0,0.4);
  3097. /* Black w/ opacity */
  3098. }
  3099. #confirmDialog794 .confirm-box {
  3100. position:relative;
  3101. color: black;
  3102. z-index:999999 !important;
  3103. background-color: #fefefe;
  3104. margin: 15% auto;
  3105. /* 15% from the top and centered */
  3106. padding: 20px;
  3107. border: 1px solid #888;
  3108. width: 30%;
  3109. /* Could be more or less, depending on screen size */
  3110. box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  3111. }
  3112. #confirmDialog794 .confirm-buttons {
  3113. text-align: right;
  3114. }
  3115. #confirmDialog794 button {
  3116. margin-left: 10px;
  3117. }
  3118.  
  3119. `
  3120. document.head.appendChild(style);
  3121.  
  3122. });
  3123.  
  3124.  
  3125. const pNavigateFinished = new Promise(resolve => {
  3126. document.addEventListener('yt-navigate-finish', resolve, true);
  3127. });
  3128.  
  3129. pNavigateFinished.then(() => {
  3130. const inputs = document.querySelectorAll('#masthead input[type="text"][name]');
  3131.  
  3132. let lastInputTextValue = null;
  3133. let busy = false;
  3134. let disableMonitoring = false;
  3135. const setGV = async (val)=>{
  3136.  
  3137. const videoId = getVideoIdByURL() || getVideoIdByElement();
  3138. if (videoId) {
  3139. const cgv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null);
  3140. if (cgv !== val || isEnable !== val) {
  3141. disableMonitoring = true;
  3142. await GM.setValue(`isEnable_aWsjF_${videoId}`, val);
  3143. await GM.setValue('lastCheck_bWsm5', Date.now());
  3144. document.documentElement.setAttribute('forceRefresh032', '');
  3145. location.reload();
  3146. }
  3147.  
  3148. }
  3149. }
  3150. const checkTextChangeF = async (evt) => {
  3151. busy = false;
  3152. const inputElem = (evt || 0).target;
  3153. if (inputElem instanceof HTMLInputElement && !disableMonitoring) {
  3154. const cv = inputElem.value;
  3155. if (cv === lastInputTextValue) return;
  3156. lastInputTextValue = cv;
  3157. if (cv === 'vvv') {
  3158.  
  3159. await setGV(false);
  3160.  
  3161. } else if (cv === 'aaa') {
  3162.  
  3163. await setGV(true);
  3164.  
  3165. }
  3166. }
  3167. }
  3168. const checkTextChange = (evt) => {
  3169. if (busy) return;
  3170. busy = true;
  3171. Promise.resolve(evt).then(checkTextChangeF)
  3172. };
  3173. for (const input of inputs) {
  3174. input.addEventListener('input', checkTextChange, false);
  3175. input.addEventListener('keydown', checkTextChange, false);
  3176. input.addEventListener('keyup', checkTextChange, false);
  3177. input.addEventListener('keypress', checkTextChange, false);
  3178. input.addEventListener('change', checkTextChange, false);
  3179. }
  3180. });
  3181.  
  3182. const autoCleanUpKey = async () => {
  3183.  
  3184. const lastCheck = await GM.getValue('lastCheck_bWsm5', null) || 0;
  3185. if (Date.now() - lastCheck < 16000) return; // 16s
  3186. GM.setValue('lastCheck_bWsm5', Date.now());
  3187. pLoad.then(async () => {
  3188. const rArr = [];
  3189. const arr = await GM.listValues();
  3190. const cv = await GM.getValue("isEnable_aWsjF", null);
  3191. const fn = async (entry) => {
  3192. try {
  3193. if (typeof entry === 'string' && entry.length > 15 && entry.startsWith('isEnable_aWsjF_')) {
  3194. const res = await GM.getValue(entry, null);
  3195. if (typeof res === 'boolean' && res === cv) {
  3196. await GM.deleteValue(entry);
  3197. rArr.push(entry);
  3198. }
  3199. }
  3200. } catch (e) {
  3201. console.warn(e);
  3202. }
  3203. }
  3204. arr.length > 1 && (await Promise.all(arr.map(fn)));
  3205. rArr.length > 0 && console.log('[YouTube Audio Only] autoCleanUpKey', rArr);
  3206. });
  3207. };
  3208.  
  3209. autoCleanUpKey();
  3210.  
  3211.  
  3212. })();
  3213.  
  3214.