YouTube: Audio Only

No Video Streaming

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

  1. // ==UserScript==
  2. // @name YouTube: Audio Only
  3. // @description No Video Streaming
  4. // @namespace UserScript
  5. // @version 1.9.4
  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. const getAppJSON = () => {
  1498. let t;
  1499. t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]');
  1500. if (t) return t;
  1501. t = document.querySelector('player-microformat-renderer.playerMicroformatRendererHost script[type="application/ld+json"]');
  1502. if (t) return t;
  1503.  
  1504. console.log('[mobile youtube audio only] getAppJSON fails.', document.querySelectorAll('script[type="application/ld+json"]').length);
  1505. return null;
  1506.  
  1507. }
  1508.  
  1509.  
  1510. let lastPlayerInfoText = '';
  1511. let mz = 0;
  1512. onVideoChangeForMobile = async () => {
  1513.  
  1514.  
  1515. let html5Container = null;
  1516.  
  1517. const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video');
  1518. if (moviePlayer) {
  1519. html5Container = moviePlayer.closest('.html5-video-container');
  1520. }
  1521.  
  1522. console.log('STx00', html5Container)
  1523. if (!html5Container) return;
  1524. let thumbnailUrl = '';
  1525.  
  1526. if (mz > 1e9) mz = 9;
  1527. let mt = ++mz;
  1528. const scriptText = await observablePromise(() => {
  1529. if (mt !== mz) return 1;
  1530. const t = getAppJSON();
  1531. const tt = (t ? t.textContent : '') || '';
  1532. if (tt === lastPlayerInfoText) return;
  1533. return tt;
  1534. }).obtain();
  1535. if (typeof scriptText !== 'string') return; // 1
  1536. lastPlayerInfoText = scriptText;
  1537.  
  1538. if (!scriptText) return;
  1539.  
  1540.  
  1541. if (SHOW_VIDEO_STATIC_IMAGE) {
  1542. console.log('STx01')
  1543.  
  1544. let idx1 = scriptText.indexOf('"thumbnailUrl"');
  1545. let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1;
  1546.  
  1547. if (idx1 === idx2 && idx1 > 0) {
  1548.  
  1549. let bk = 0;
  1550. let j = -1;
  1551. for (let i = idx1; i < scriptText.length; i++) {
  1552. if (i > idx1 + 20 && bk === 0) {
  1553. j = i;
  1554. break;
  1555. }
  1556. let t = scriptText.charAt(i);
  1557. if (t === '[') bk++;
  1558. else if (t === ']') bk--;
  1559. else if (t === '{') bk++;
  1560. else if (t === '}') bk--;
  1561. }
  1562.  
  1563.  
  1564. if (j > idx1) {
  1565.  
  1566. let thumbnailUrlString = scriptText.substring(idx1, j);
  1567. let thumbnailUrlObject = null;
  1568.  
  1569. try {
  1570. thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`);
  1571.  
  1572. } catch (e) { }
  1573.  
  1574. const thumbnails = thumbnailUrlObject.thumbnailUrl;
  1575.  
  1576. if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') {
  1577. if (thumbnails[0] && thumbnails[0].length > 3) {
  1578. thumbnailUrl = thumbnails[0];
  1579. }
  1580. }
  1581. }
  1582.  
  1583. }
  1584. console.log('STx02', thumbnailUrl)
  1585.  
  1586. // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0;
  1587.  
  1588. // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0);
  1589.  
  1590. // if (thumbnails && thumbnails.length >= 1) {
  1591. // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1592.  
  1593. // }
  1594. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  1595. html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  1596. } else {
  1597. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1598. }
  1599.  
  1600. }
  1601.  
  1602.  
  1603. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40);
  1604.  
  1605. await delayPn(80);
  1606. const audio = moviePlayer;
  1607. if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) {
  1608. await audio.click();
  1609. }
  1610.  
  1611. }
  1612.  
  1613. let player0 = null;
  1614. let mgg = null;
  1615. const mff = function (e) {
  1616. if (!player0) {
  1617. if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') {
  1618. player0 = e.target
  1619. if (mgg) mgg();
  1620. }
  1621. }
  1622.  
  1623.  
  1624. // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) {
  1625.  
  1626. // onVideoChangeForMobile();
  1627. // }
  1628.  
  1629. }
  1630.  
  1631. document.addEventListener('player-initialized', mff, true);
  1632. document.addEventListener('player-state-change', mff, true);
  1633. document.addEventListener('player-ad-state-change', mff, true);
  1634. document.addEventListener('player-detailed-error', mff, true);
  1635. document.addEventListener('player-error', mff, true);
  1636. document.addEventListener('on-play-autonav-video', mff, true);
  1637. document.addEventListener('on-play-previous-autonav-video', mff, true);
  1638. document.addEventListener('player-fullscreen-change', mff, true);
  1639. document.addEventListener('player-fullscreen-toggled', mff, true);
  1640. document.addEventListener('player-dom-paused', mff, true);
  1641. document.addEventListener('yt-show-toast', mff, true);
  1642. document.addEventListener('yt-innertube-command', mff, true);
  1643. document.addEventListener('yt-update-c3-companion', mff, true);
  1644. document.addEventListener('video-data-change', mff, true);
  1645. document.addEventListener('video-progress', mff, true);
  1646. document.addEventListener('local-media-change', mff, true);
  1647.  
  1648.  
  1649. let tc = false;
  1650. // let pw = null;
  1651. (async () => {
  1652.  
  1653. let player__;
  1654.  
  1655. const getAudioElement = () => {
  1656. const elm = player__ || player0;
  1657. const audio = elm && elm.isConnected === true ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null;
  1658. return audio;
  1659. }
  1660.  
  1661. const asyncStateChange = async (audio, k) => {
  1662. const player_ = player__;
  1663. if (!player_) return;
  1664. if (typeof player_.getPlayerState !== 'function') return;
  1665.  
  1666. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1667. // try {
  1668. // if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  1669. // } catch (e) {
  1670. // }
  1671. };
  1672. const triggerPlaying = async () => {
  1673. await player_.cancelPlayback();
  1674. await player_.pauseVideo();
  1675. await player_.playVideo();
  1676. };
  1677. const seekToLiveHeadForLiveStream = async () => {
  1678. try {
  1679. await player_.seekToLiveHead();
  1680. if ((await player_.isAtLiveHead()) === true) {
  1681. await player_.seekToStreamTime();
  1682. return true;
  1683. }
  1684. } catch (e) {
  1685. console.log('error_F9', e);
  1686. }
  1687. };
  1688. const fixLiveAudioFn = async () => {
  1689. if (audio.paused === true) {
  1690. await player_.clearVideo(); // avoid error in live streaming
  1691. await player_.clearQueue(); // avoid error in live streaming
  1692. await delayPn(300);
  1693. for (let i = 0; i < 3; i++) {
  1694. if (audio.readyState === 0) {
  1695. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1696. }
  1697. }
  1698. if (k === -1) {
  1699. await refreshAllStaleEntitiesForNonReadyAudio();
  1700. } else if (k === 3) {
  1701. while (audio.readyState === 0) {
  1702. await refreshAllStaleEntitiesForNonReadyAudio();
  1703. await triggerPlaying();
  1704. await delayPn(300);
  1705. }
  1706. // console.log(8809,audio.readyState)
  1707. }
  1708. } else if (audio.paused === false) {
  1709. if (!player_.isAtLiveHead()) {
  1710. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1711. }
  1712. while (audio.readyState === 0) {
  1713. await refreshAllStaleEntitiesForNonReadyAudio();
  1714. await triggerPlaying();
  1715. await delayPn(300);
  1716. }
  1717. if (!player_.isAtLiveHead()) {
  1718. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1719. }
  1720. await refreshAllStaleEntitiesForNonReadyAudio();
  1721. if (audio.readyState > 0 && audio.paused === true) {
  1722. await triggerPlaying();
  1723. }
  1724. }
  1725.  
  1726. }
  1727. try {
  1728.  
  1729. let ns23 = audio.networkState == 2 || audio.networkState == 3
  1730. // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted)
  1731.  
  1732. if (!ns23 && k === player_.getPlayerState()) {
  1733. if (k === -1 && audio.readyState === 0) {
  1734. const et = await mediaNetworkStateReady(audio);
  1735. if (audio.isConnected === false || player_.getPlayerState() === 5) return;
  1736. ns23 = audio.networkState == 2 || audio.networkState == 3;
  1737. console.log(523, ns23, et, player_.getPlayerState());
  1738. if (player_.getPlayerState() !== -1) return;
  1739. } else {
  1740. console.log(527, k, audio.readyState, audio.networkState)
  1741. }
  1742. }
  1743.  
  1744. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300);
  1745.  
  1746. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) {
  1747. tc = true;
  1748. }
  1749. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1750. await delayPn(200);
  1751. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1752. // console.log(8806)
  1753. await fixLiveAudioFn();
  1754. }
  1755. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1756. await seekToLiveHeadForLiveStream();
  1757. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) {
  1758. await delayPn(60);
  1759. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) {
  1760. // console.log(8807)
  1761. await fixLiveAudioFn();
  1762. }
  1763.  
  1764. }
  1765.  
  1766. } catch (e) {
  1767. console.log('error_F10', e)
  1768. }
  1769.  
  1770. };
  1771. const _onPlayerStateChange = (e) => {
  1772. if (e && (e || 0).target) {
  1773. player__ = e.target
  1774. }
  1775. const player_ = player__;
  1776. try {
  1777. if (!player_) return;
  1778. let k = null;
  1779. if (e && e.detail && e.detail.state) {
  1780. k = e.detail.state
  1781. }
  1782. if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) {
  1783. const audio = getAudioElement();
  1784. if (audio) asyncStateChange(audio, k);
  1785. }
  1786. } catch (e) {
  1787. console.log('error_F11', e)
  1788. }
  1789. };
  1790.  
  1791. let idleAudioActivatePending = false;
  1792.  
  1793. const _onVideoProgress = (e) => {
  1794. if (e && (e || 0).target) {
  1795. player__ = e.target
  1796. }
  1797. const player_ = player__;
  1798. if (!player_) return;
  1799. updateLastActiveTimeAsync(player_);
  1800. if (tc) {
  1801. tc = false;
  1802. if (!idleAudioActivatePending) {
  1803. idleAudioActivatePending = true;
  1804. }
  1805. }
  1806. };
  1807.  
  1808. mgg = function () {
  1809. const player_ = player0;
  1810. if (player_) {
  1811. const state0 = player_.getPlayerState();
  1812. if (typeof state0 === 'number') {
  1813. _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } });
  1814. }
  1815. }
  1816. }
  1817.  
  1818. document.addEventListener('player-state-change', _onPlayerStateChange, true);
  1819.  
  1820. document.addEventListener('video-progress', _onVideoProgress, true);
  1821.  
  1822. })();
  1823.  
  1824. // document.addEventListener('DOMContentLoaded', (evt) => {
  1825. // const mo = new MutationObserver((mutations)=>{
  1826. // console.log(5899, mutations)
  1827. // });
  1828. // mo.observe(document, {subtree: true, childList: true})
  1829. // })
  1830.  
  1831. // window.addEventListener('onReady', (evt) => {
  1832. // console.log(6811)
  1833. // }, true);
  1834.  
  1835. // window.addEventListener('localmediachange', (evt) => {
  1836. // console.log(6812)
  1837. // }, true);
  1838.  
  1839. // window.addEventListener('onVideoDataChange', (evt) => {
  1840. // console.log(6813)
  1841. // }, true);
  1842.  
  1843. window.addEventListener('state-navigateend', async (evt) => {
  1844.  
  1845.  
  1846. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1847. ytConfigFix(config_);
  1848.  
  1849. try {
  1850. if (clickLockFn && clickTarget) {
  1851.  
  1852. let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video');
  1853. if (!a) return;
  1854.  
  1855. if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1856.  
  1857. const pr = new Promise(resolve => {
  1858.  
  1859. document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false });
  1860.  
  1861. }).then();
  1862.  
  1863. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1864. await delayPn(1);
  1865.  
  1866. if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1867. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1868. await delayPn(1);
  1869. }
  1870.  
  1871. delayRun(pr);
  1872.  
  1873. }
  1874.  
  1875. }
  1876.  
  1877. } catch (e) { console.log('error_F12', e) }
  1878.  
  1879.  
  1880. }, false);
  1881.  
  1882.  
  1883.  
  1884. // document.addEventListener('volumechange', (evt) => {
  1885. // console.log('volumechange')
  1886. // }, true)
  1887. // document.addEventListener('play', (evt) => {
  1888. // console.log('play')
  1889. // }, true)
  1890.  
  1891.  
  1892. // document.addEventListener('player-initialized', (evt) => {
  1893. // console.log(evt.type)
  1894. // }, true)
  1895. // document.addEventListener('renderer-module-load-start', (evt) => {
  1896. // console.log(evt.type)
  1897. // }, true)
  1898. // document.addEventListener('video-data-change', (evt) => {
  1899. // console.log(evt.type)
  1900. // }, true)
  1901. // document.addEventListener('player-state-change', (evt) => {
  1902. // console.log(evt.type)
  1903. // }, true)
  1904. // document.addEventListener('updateui', (evt) => {
  1905. // console.log(evt.type)
  1906. // }, true)
  1907. // document.addEventListener('renderer-module-load-end', (evt) => {
  1908. // console.log(evt.type)
  1909. // }, true)
  1910.  
  1911. // document.addEventListener('player-autonav-pause', (evt) => {
  1912. // console.log(evt.type)
  1913. // }, true)
  1914.  
  1915.  
  1916.  
  1917. // document.addEventListener('player-ad-state-change', (evt) => {
  1918. // console.log(evt.type)
  1919. // }, true)
  1920.  
  1921. // document.addEventListener('player-detailed-error', (evt) => {
  1922. // console.log(evt.type)
  1923. // }, true)
  1924.  
  1925. // document.addEventListener('player-error', (evt) => {
  1926. // console.log(evt.type)
  1927. // }, true)
  1928.  
  1929. // document.addEventListener('on-play-autonav-video', (evt) => {
  1930. // console.log(evt.type)
  1931. // }, true)
  1932.  
  1933. // document.addEventListener('on-play-previous-autonav-video', (evt) => {
  1934. // console.log(evt.type)
  1935. // }, true)
  1936.  
  1937. // document.addEventListener('player-fullscreen-change', (evt) => {
  1938. // console.log(evt.type)
  1939. // }, true)
  1940.  
  1941. // document.addEventListener('player-fullscreen-toggled', (evt) => {
  1942. // console.log(evt.type)
  1943. // }, true)
  1944.  
  1945. // document.addEventListener('player-dom-paused', (evt) => {
  1946. // console.log(evt.type)
  1947. // }, true)
  1948.  
  1949. // document.addEventListener('yt-show-toast', (evt) => {
  1950. // console.log(evt.type)
  1951. // }, true)
  1952. // document.addEventListener('yt-innertube-command', (evt) => {
  1953. // console.log(evt.type)
  1954. // }, true)
  1955. // document.addEventListener('yt-update-c3-companion', (evt) => {
  1956. // console.log(evt.type)
  1957. // }, true)
  1958. // document.addEventListener('video-progress', (evt) => {
  1959. // // console.log(evt.type)
  1960. // }, true)
  1961. // document.addEventListener('localmediachange', (evt) => {
  1962. // console.log(evt.type)
  1963. // }, true)
  1964.  
  1965.  
  1966.  
  1967. // window.addEventListener('player-initialized', (evt) => {
  1968. // console.log(evt.type)
  1969. // }, true)
  1970. // window.addEventListener('renderer-module-load-start', (evt) => {
  1971. // console.log(evt.type)
  1972. // }, true)
  1973. // window.addEventListener('video-data-change', (evt) => {
  1974. // console.log(evt.type)
  1975. // }, true)
  1976. // window.addEventListener('player-state-change', (evt) => {
  1977. // console.log(evt.type)
  1978. // }, true)
  1979. // window.addEventListener('updateui', (evt) => {
  1980. // console.log(evt.type)
  1981. // }, true)
  1982. // window.addEventListener('renderer-module-load-end', (evt) => {
  1983. // console.log(evt.type)
  1984. // }, true)
  1985.  
  1986. // window.addEventListener('player-autonav-pause', (evt) => {
  1987. // console.log(evt.type)
  1988. // }, true)
  1989.  
  1990.  
  1991.  
  1992. // window.addEventListener('player-ad-state-change', (evt) => {
  1993. // console.log(evt.type)
  1994. // }, true)
  1995.  
  1996. // window.addEventListener('player-detailed-error', (evt) => {
  1997. // console.log(evt.type)
  1998. // }, true)
  1999.  
  2000. // window.addEventListener('player-error', (evt) => {
  2001. // console.log(evt.type)
  2002. // }, true)
  2003.  
  2004. // window.addEventListener('on-play-autonav-video', (evt) => {
  2005. // console.log(evt.type)
  2006. // }, true)
  2007.  
  2008. // window.addEventListener('on-play-previous-autonav-video', (evt) => {
  2009. // console.log(evt.type)
  2010. // }, true)
  2011.  
  2012. // window.addEventListener('player-fullscreen-change', (evt) => {
  2013. // console.log(evt.type)
  2014. // }, true)
  2015.  
  2016. // window.addEventListener('player-fullscreen-toggled', (evt) => {
  2017. // console.log(evt.type)
  2018. // }, true)
  2019.  
  2020. // window.addEventListener('player-dom-paused', (evt) => {
  2021. // console.log(evt.type)
  2022. // }, true)
  2023.  
  2024. // window.addEventListener('yt-show-toast', (evt) => {
  2025. // console.log(evt.type)
  2026. // }, true)
  2027. // window.addEventListener('yt-innertube-command', (evt) => {
  2028. // console.log(evt.type)
  2029. // }, true)
  2030. // window.addEventListener('yt-update-c3-companion', (evt) => {
  2031. // console.log(evt.type)
  2032. // }, true)
  2033. // window.addEventListener('video-progress', (evt) => {
  2034. // // console.log(evt.type)
  2035. // }, true)
  2036. // window.addEventListener('localmediachange', (evt) => {
  2037. // console.log(evt.type)
  2038. // }, true)
  2039.  
  2040.  
  2041.  
  2042. // document.addEventListener('player-error', (evt) => {
  2043. // console.log(3001, evt.type, evt)
  2044. // }, true)
  2045. // document.addEventListener('player-detailed-error', (evt) => {
  2046. // console.log(3002, evt.type, evt)
  2047. // }, true)
  2048.  
  2049.  
  2050.  
  2051. async function delayRun(pr) {
  2052.  
  2053. let q = document.querySelector('#movie_player');
  2054. if (!q) return;
  2055. let a = document.querySelector('.video-stream.html5-main-video');
  2056. if (!a) return;
  2057.  
  2058. await pr.then();
  2059.  
  2060. if (fa !== 1) {
  2061. return;
  2062. } else if (a.muted === true) {
  2063. return;
  2064. } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) {
  2065. if (a.paused === false) return;
  2066. } else {
  2067. return;
  2068. }
  2069.  
  2070. if (document.querySelector('.player-controls-content')) return;
  2071.  
  2072. if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) {
  2073.  
  2074. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  2075.  
  2076. }
  2077.  
  2078. if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) {
  2079.  
  2080. if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead();
  2081. if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) {
  2082. if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime();
  2083. }
  2084. }
  2085.  
  2086. }
  2087.  
  2088. durationchangeForMobile = true;
  2089.  
  2090. }
  2091.  
  2092. attachOneTimeEvent('yt-action', function () {
  2093. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  2094. ytConfigFix(config_);
  2095. });
  2096.  
  2097. let prepared = false;
  2098. function prepare() {
  2099. if (prepared) return;
  2100. prepared = true;
  2101.  
  2102. if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') {
  2103.  
  2104. for (const [k, v] of Object.entries(_yt_player)) {
  2105.  
  2106. const p = typeof v === 'function' ? v.prototype : 0;
  2107.  
  2108. if (p
  2109. && typeof p.clone === 'function'
  2110. && typeof p.get === 'function' && typeof p.set === 'function'
  2111. && typeof p.isEmpty === 'undefined' && typeof p.forEach === 'undefined'
  2112. && typeof p.clear === 'undefined'
  2113. ) {
  2114.  
  2115. key = k;
  2116.  
  2117. }
  2118.  
  2119. }
  2120.  
  2121. }
  2122.  
  2123. if (key) {
  2124.  
  2125. const ClassX = _yt_player[key];
  2126. _yt_player[key] = class extends ClassX {
  2127. constructor(...args) {
  2128.  
  2129. if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = '';
  2130. super(...args);
  2131.  
  2132. }
  2133. }
  2134. _yt_player[key].luX1Y = 1;
  2135. prototypeInherit(_yt_player[key].prototype, ClassX.prototype);
  2136. }
  2137.  
  2138. }
  2139. let s3 = Symbol();
  2140.  
  2141. generalRegister('deviceIsAudioOnly', s3, (p) => {
  2142. return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p)
  2143. }, {
  2144.  
  2145. get() {
  2146. return this[s3];
  2147. },
  2148. set(nv) {
  2149. if (typeof nv === 'boolean') this[s3] = true;
  2150. else this[s3] = undefined;
  2151. prepare();
  2152. return true;
  2153. },
  2154. enumerable: false,
  2155. configurable: true
  2156.  
  2157. });
  2158.  
  2159.  
  2160. let s1 = Symbol();
  2161. let s2 = Symbol();
  2162. Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', {
  2163. get() {
  2164. // console.log(501, this.constructor.prototype)
  2165. return undefined;
  2166. },
  2167. set(nv) {
  2168. return true;
  2169. },
  2170. enumerable: false,
  2171. configurable: true
  2172. });
  2173.  
  2174. Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', {
  2175. get() {
  2176. // console.log(502, this.constructor.prototype)
  2177. return this[s1];
  2178. },
  2179. set(nv) {
  2180. if (typeof nv === 'boolean') this[s1] = false;
  2181. else this[s1] = undefined;
  2182. return true;
  2183. },
  2184. enumerable: false,
  2185. configurable: true
  2186. });
  2187.  
  2188. Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', {
  2189. get() {
  2190. // console.log(503, this.constructor.prototype)
  2191. return this[s2];
  2192. },
  2193. set(nv) {
  2194. if (typeof nv === 'boolean') this[s2] = false;
  2195. else this[s2] = undefined;
  2196. return true;
  2197. },
  2198. enumerable: false,
  2199. configurable: true
  2200. });
  2201.  
  2202.  
  2203. const supportedFormatsConfig = () => {
  2204.  
  2205. function typeTest(type) {
  2206. if (typeof type === 'string' && type.startsWith('video/')) {
  2207. return false;
  2208. }
  2209. }
  2210.  
  2211. // return a custom MIME type checker that can defer to the original function
  2212. function makeModifiedTypeChecker(origChecker) {
  2213. // Check if a video type is allowed
  2214. return function (type) {
  2215. let res = undefined;
  2216. if (type === undefined) res = false;
  2217. else {
  2218. res = typeTest.call(this, type);
  2219. }
  2220. if (res === undefined) res = origChecker.apply(this, arguments);
  2221. return res;
  2222. };
  2223. }
  2224.  
  2225. // Override video element canPlayType() function
  2226. const proto = (HTMLVideoElement || 0).prototype;
  2227. if (proto && typeof proto.canPlayType == 'function') {
  2228. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  2229. }
  2230.  
  2231. // Override media source extension isTypeSupported() function
  2232. const mse = window.MediaSource;
  2233. // Check for MSE support before use
  2234. if (mse && typeof mse.isTypeSupported == 'function') {
  2235. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  2236. }
  2237.  
  2238. };
  2239.  
  2240. supportedFormatsConfig();
  2241.  
  2242.  
  2243. PATCH_MEDIA_PUBLISH && (async ()=>{
  2244.  
  2245.  
  2246. const _yt_player_observable = observablePromise(() => {
  2247. return (((window || 0)._yt_player || 0) || 0);
  2248. });
  2249.  
  2250. const addProtoToArr = (parent, key, arr) => {
  2251.  
  2252.  
  2253. let isChildProto = false;
  2254. for (const sr of arr) {
  2255. if (parent[key].prototype instanceof parent[sr]) {
  2256. isChildProto = true;
  2257. break;
  2258. }
  2259. }
  2260.  
  2261. if (isChildProto) return;
  2262.  
  2263. arr = arr.filter(sr => {
  2264. if (parent[sr].prototype instanceof parent[key]) {
  2265. return false;
  2266. }
  2267. return true;
  2268. });
  2269.  
  2270. arr.push(key);
  2271.  
  2272. return arr;
  2273.  
  2274.  
  2275. };
  2276. /*
  2277.  
  2278. const getD0 = (_yt_player) => {
  2279.  
  2280. const w = 'D0';
  2281.  
  2282. let arr = [];
  2283.  
  2284. for (const [k, v] of Object.entries(_yt_player)) {
  2285.  
  2286. const p = typeof v === 'function' ? v.prototype : 0;
  2287. if (p
  2288. && typeof p.playVideo === 'function' && p.playVideo.length === 1
  2289. && typeof p.getVisibilityState === 'function' && p.getVisibilityState.length === 8
  2290. && typeof p.getVideoData === 'function' && p.getVideoData.length === 0
  2291. && typeof p.seekTo === 'function' && p.seekTo.length === 5
  2292. && typeof p.pauseVideo === 'function' && p.pauseVideo.length === 2
  2293. && typeof p.stopVideo === 'function' && p.stopVideo.length === 1
  2294. && typeof p.getPresentingPlayerType === 'function' && p.getPresentingPlayerType.length === 1
  2295. && typeof p.getCurrentTime === 'function' && p.getCurrentTime.length === 3
  2296. && typeof p.cancelPlayback === 'function' && p.cancelPlayback.length === 2
  2297. // && !p.getPlayerType
  2298.  
  2299. ) {
  2300. arr = addProtoToArr(_yt_player, k, arr) || arr;
  2301.  
  2302.  
  2303. }
  2304.  
  2305. }
  2306.  
  2307. if (arr.length === 0) {
  2308.  
  2309. console.warn(`Key does not exist. [${w}]`);
  2310. } else {
  2311.  
  2312. console.log(`[${w}]`, arr);
  2313. return arr[0];
  2314. }
  2315.  
  2316. }
  2317. */
  2318.  
  2319. const gets0 = (_yt_player) => {
  2320.  
  2321. const w = 's0';
  2322.  
  2323. let arr = [];
  2324.  
  2325. for (const [k, v] of Object.entries(_yt_player)) {
  2326.  
  2327. const p = typeof v === 'function' ? v.prototype : 0;
  2328. if (p
  2329. && typeof p.isBackground === 'function' && p.isBackground.length === 0
  2330. && typeof p.getPlaybackRate === 'function' && p.getPlaybackRate.length === 0
  2331. && typeof p.publish === 'function' && p.publish.length === 2
  2332. && typeof p.isAtLiveHead === 'function' && p.isAtLiveHead.length === 2
  2333.  
  2334.  
  2335.  
  2336. // && !p.getPlayerType
  2337.  
  2338. ) {
  2339. arr = addProtoToArr(_yt_player, k, arr) || arr;
  2340.  
  2341.  
  2342. }
  2343.  
  2344. }
  2345.  
  2346. if (arr.length === 0) {
  2347.  
  2348. console.warn(`Key does not exist. [${w}]`);
  2349. } else {
  2350.  
  2351. console.log(`[${w}]`, arr);
  2352. return arr[0];
  2353. }
  2354.  
  2355. };
  2356.  
  2357. const printObject = (b)=>{
  2358. return JSON.stringify( Object.entries(b||{}).filter(e=>typeof (e[1]||0)!=='object'));
  2359. };
  2360.  
  2361. /*
  2362. (async () => {
  2363. // rAf scheduling
  2364. const _yt_player = await _yt_player_observable.obtain();
  2365. if (!_yt_player || typeof _yt_player !== 'object') return;
  2366. let keyD0 = getD0(_yt_player);
  2367. if (!keyD0) return;
  2368. const g = _yt_player
  2369. let k = keyD0
  2370. const gk = g[k];
  2371. if (typeof gk !== 'function') return;
  2372. const gkp = gk.prototype;
  2373.  
  2374.  
  2375. gkp.playVideo48 = gkp.playVideo;
  2376. gkp.playVideo = function(a) {
  2377. let r = this.playVideo48(a);
  2378. // console.log('gkpD0 playVideo',r, a)
  2379. return r;
  2380. }
  2381.  
  2382. gkp.getVisibilityState48 = gkp.getVisibilityState;
  2383. gkp.getVisibilityState = function(a, b, c, d, e, f, h, l) {
  2384. let r = this.getVisibilityState48(a, b, c, d, e, f, h, l);
  2385. // console.log('gkpD0 getVisibilityState',r, a,b,c,d,e,f,h,l)
  2386. r = 0;
  2387. return r;
  2388. }
  2389.  
  2390.  
  2391. gkp.getVideoData48 = gkp.getVideoData;
  2392. gkp.getVideoData = function() {
  2393. let r = this.getVideoData48();
  2394. // console.log('gkpD0 getVideoData',r)
  2395. return r;
  2396. }
  2397.  
  2398. gkp.seekTo48 = gkp.seekTo;
  2399. gkp.seekTo = function(a, b, c, d, e) {
  2400. let r = this.seekTo48(a, b, c, d, e);
  2401. // console.log('gkpD0 seekTo',r, a,b,c,d,e)
  2402. return r;
  2403. }
  2404.  
  2405. gkp.pauseVideo48 = gkp.pauseVideo;
  2406. gkp.pauseVideo = function(a, b) {
  2407. let r = this.pauseVideo48(a, b);
  2408. // console.log('gkpD0 pauseVideo',r, a,b);
  2409. return r;
  2410. }
  2411.  
  2412.  
  2413. gkp.stopVideo48 = gkp.stopVideo;
  2414. gkp.stopVideo = function(a) {
  2415. let r = this.stopVideo48(a);
  2416. // console.log('gkpD0 stopVideo',r,a)
  2417. return r;
  2418. }
  2419.  
  2420.  
  2421.  
  2422.  
  2423. gkp.getPresentingPlayerType48 = gkp.getPresentingPlayerType;
  2424. gkp.getPresentingPlayerType = function(a) {
  2425. let r = this.getPresentingPlayerType48(a);
  2426. // console.log('gkpD0 getPresentingPlayerType',r,a)
  2427. return r;
  2428. }
  2429.  
  2430. gkp.getCurrentTime48 = gkp.getCurrentTime;
  2431. gkp.getCurrentTime = function(a, b, c) {
  2432. let r = this.getCurrentTime48(a, b, c);
  2433. // console.log('gkpD0 getCurrentTime',r, a,b,c)
  2434. return r;
  2435. }
  2436.  
  2437. gkp.cancelPlayback48 = gkp.cancelPlayback;
  2438. gkp.cancelPlayback = function(a, b) {
  2439. let r = this.cancelPlayback48(a, b);
  2440. // console.log('gkpD0 cancelPlayback',r, a,b);
  2441. return r;
  2442. }
  2443. })();
  2444. */
  2445.  
  2446.  
  2447.  
  2448. /**
  2449. *
  2450. *
  2451.  
  2452. g.k.mL = function(a) {
  2453. var b = a.target.Gf();
  2454. if (this.mediaElement && this.mediaElement.Gf() && this.mediaElement.Gf() === b) {
  2455. ehb(this, a.type);
  2456. switch (a.type) {
  2457. case "error":
  2458. var c = yFa(this.mediaElement) || ""
  2459. , d = this.mediaElement.xf();
  2460. if (c === "capability.changed") {
  2461. this.L("html5_restart_on_capability_change") ? (this.ma("capchg", {
  2462. msg: d
  2463. }),
  2464. F_(this, !0)) : u0(this);
  2465. return
  2466. }
  2467. if (this.mediaElement.hasError() && (Ndb(this.al, c, {
  2468. msg: d
  2469. }) || g.zS(this.videoData) && this.wb && this.wb.handleError(c)))
  2470. return;
  2471. if (this.isBackground() && this.mediaElement.fh() === 4) {
  2472. this.So();
  2473. x0(this, "unplayable");
  2474. return
  2475. }
  2476. break;
  2477. case "durationchange":
  2478. c = this.mediaElement.getDuration();
  2479. isFinite(c) && (!this.Qa || c > 0) && c !== 1 && this.Hl(c);
  2480. break;
  2481. case "ratechange":
  2482. this.ya && this.ya.setPlaybackRate(this.mediaElement.getPlaybackRate());
  2483. xfb(this.Ch);
  2484. this.wc().onPlaybackRateChange(this.getPlaybackRate());
  2485. break;
  2486. case "loadedmetadata":
  2487. ghb(this);
  2488. this.publish("onLoadedMetadata");
  2489. W5a(this);
  2490. c = this.bf();
  2491. this.videoData.SB && (this.videoData.SB = c);
  2492. break;
  2493. case "loadstart":
  2494. W5a(this);
  2495. break;
  2496. case "progress":
  2497. case "suspend":
  2498. this.Uc();
  2499. this.publish("onLoadProgress", this, this.Sw());
  2500. break;
  2501. case "playing":
  2502. this.Rb.uv("plev");
  2503. this.bT && !k0(this) && (this.bT = !1,
  2504. this.isAtLiveHead() || (this.logger.debug("seek to infinity on PLAYING"),
  2505. this.seekTo(Infinity, {
  2506. kd: "videoplayer_onPlaying"
  2507. })));
  2508. break;
  2509. case "timeupdate":
  2510. c = this.mediaElement && !this.mediaElement.getCurrentTime();
  2511. d = this.mediaElement && this.mediaElement.Tk() === 0;
  2512. if (c && (!this.VK || d))
  2513. return;
  2514. this.VK = this.VK || !!this.mediaElement.getCurrentTime();
  2515. Vgb(this);
  2516. this.Uc();
  2517. if (!this.mediaElement || this.mediaElement.Gf() !== b)
  2518. return;
  2519. this.publish("onVideoProgress", this, this.getCurrentTime());
  2520. break;
  2521. case "waiting":
  2522. if (this.mediaElement.Vw().length > 0 && this.mediaElement.Eh().length === 0 && this.mediaElement.getCurrentTime() > 0 && this.mediaElement.getCurrentTime() < 5 && this.ya)
  2523. return;
  2524. 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(),
  2525. c.bh = sK(this.mediaElement).toFixed(3),
  2526. this.ma("uwe", c));
  2527. g.zS(this.videoData) && this.wb && n7a(this.wb, this.mediaElement.getCurrentTime());
  2528. break;
  2529. case "resize":
  2530. ghb(this);
  2531. this.videoData.B && this.videoData.B.video.quality === "auto" && this.publish("internalvideoformatchange", this.videoData, !1);
  2532. break;
  2533. case "pause":
  2534. if (this.TW && g.pF(this.playerState, 8) && !g.pF(this.playerState, 1024) && this.getCurrentTime() === 0 && g.VB) {
  2535. x0(this, "safari_autoplay_disabled");
  2536. return
  2537. }
  2538. }
  2539. if (this.mediaElement && this.mediaElement.Gf() === b) {
  2540. dgb(this.Tc, a, this.wb || void 0);
  2541. this.publish("videoelementevent", a);
  2542. b = this.playerState;
  2543. d = this.bE;
  2544. var e = this.mediaElement;
  2545. c = this.videoData.clientPlaybackNonce;
  2546. var f = g.zS(this.videoData) && this.wb ? jY(this.wb) : void 0;
  2547. if (!g.pF(b, 128)) {
  2548. var h = b.state;
  2549. e = e ? e : a.target;
  2550. var l = e.getCurrentTime();
  2551. if (!g.pF(b, 64) || a.type !== "ended" && a.type !== "pause") {
  2552. f = f || e.getDuration();
  2553. f = e.isEnded() || l > 1 && Math.abs(l - f) < 1.1;
  2554. var m = a.type === "pause" && e.isEnded();
  2555. l = a.type === "ended" || a.type === "waiting" || a.type === "timeupdate" && !g.pF(b, 4) && !a0(d, l);
  2556. if (m || f && l)
  2557. e.KJ() > 0 && e.Gf() && (h = 14);
  2558. else
  2559. switch (a.type) {
  2560. case "error":
  2561. yFa(e) && (h |= 128);
  2562. break;
  2563. case "pause":
  2564. g.pF(b, 256) ? (h ^= 256) || (h = 64) : g.pF(b, 32) || g.pF(b, 2) || g.pF(b, 4) || (h = 4,
  2565. g.pF(b, 1) && g.pF(b, 8) && (h |= 1));
  2566. break;
  2567. case "playing":
  2568. l = h;
  2569. h = (h | 8) & -1093;
  2570. l & 4 ? (h |= 1,
  2571. uK(d, e)) : a0(d, e.getCurrentTime()) && (h &= -2);
  2572. g.pF(b, 1) && uK(d, e) && (h |= 1);
  2573. break;
  2574. case "seeking":
  2575. h |= 16;
  2576. g.pF(b, 8) && (h |= 1);
  2577. h &= -3;
  2578. break;
  2579. case "seeked":
  2580. h &= -17;
  2581. uK(d, e);
  2582. break;
  2583. case "waiting":
  2584. g.pF(b, 2) || (h |= 1);
  2585. uK(d, e);
  2586. break;
  2587. case "timeupdate":
  2588. l = g.pF(b, 16),
  2589. f = g.pF(b, 4),
  2590. (g.pF(b, 8) || l) && !f && a0(d, e.getCurrentTime()) && (h = 8),
  2591. uK(d, e) && (h |= 1)
  2592. }
  2593. }
  2594. d = h;
  2595. h = null;
  2596. d & 128 && (h = a.target,
  2597. e = yFa(h),
  2598. l = 1,
  2599. e ? (e === "capability.changed" && (l = 2),
  2600. f = "GENERIC_WITHOUT_LINK",
  2601. m = h.uc(),
  2602. m.mediaElem = "1",
  2603. /AUDIO_RENDERER/.test(h.xf()) && (f = "HTML5_AUDIO_RENDERER_ERROR"),
  2604. h = {
  2605. errorCode: e,
  2606. errorMessage: g.JV[f] || "",
  2607. bP: f,
  2608. KL: yJ(m),
  2609. rJ: l,
  2610. cpn: b.Pg ? b.Pg.cpn : ""
  2611. }) : h = null,
  2612. h && (h.cpn = c));
  2613. b = vK(b, d, h)
  2614. }
  2615. !g.pF(this.playerState, 1) && g.pF(b, 1) && dhb(this, "evt" + a.type);
  2616. this.Ic(b)
  2617. }
  2618. }
  2619. }
  2620. ;
  2621. *
  2622. *
  2623. */
  2624.  
  2625.  
  2626.  
  2627.  
  2628. (async () => {
  2629. // rAf scheduling
  2630. const _yt_player = await _yt_player_observable.obtain();
  2631. if (!_yt_player || typeof _yt_player !== 'object') return;
  2632. let keys0 = gets0(_yt_player);
  2633. if (!keys0) return;
  2634. const g = _yt_player
  2635. let k = keys0
  2636. const gk = g[k];
  2637. if (typeof gk !== 'function') return;
  2638. const gkp = gk.prototype;
  2639.  
  2640.  
  2641. // gkp.isBackground48 = gkp.isBackground;
  2642. // gkp.isBackground = function() {
  2643. // if(!this?.visibility?.isBackground88){
  2644. // this.visibility.isBackground88 = 1;
  2645. // this.visibility.isBackground = function(){
  2646. // return false;
  2647. // }
  2648. // }
  2649. // // console.log('gkps0', 'isBackground', this.visibility)
  2650. // // return false;
  2651. // // if(!this.mediaElement || !(this.mediaElement.readyState>=4)){
  2652. // // return false;
  2653. // // }
  2654. // // console.log(1882,)
  2655. // return this.isBackground48();
  2656. // }
  2657.  
  2658. gkp.publish48 = gkp.publish;
  2659. gkp.publish33 = async function(a,b){
  2660.  
  2661. const player_ = kRef(globalPlayer);
  2662. let publishStatus = 0;
  2663. const media = this.mediaElement;
  2664.  
  2665. if(a==='internalaudioformatchange' && typeof (b.author||0) === 'string' && media && player_){
  2666.  
  2667. await player_.clearVideo(); // avoid error in live streaming
  2668. await player_.clearQueue(); // avoid error in live streaming
  2669. await refreshAllStaleEntitiesForNonReadyAudio();
  2670. // await player_.cancelPlayback();
  2671. publishStatus = media.__publishStatus17__ = 100;
  2672. }
  2673.  
  2674.  
  2675.  
  2676.  
  2677.  
  2678. const domMedia = media ? Object.values(media).filter(e => e instanceof HTMLMediaElement) : [];
  2679. if (this.mediaElement && a !== 'internalvideoformatchange' && player_ && domMedia.length === 1) {
  2680.  
  2681. const audio = domMedia[0];
  2682.  
  2683.  
  2684.  
  2685. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  2686. try {
  2687. if (audio.readyState == 0 && audio.isConnected === true) await player_.refreshAllStaleEntities();
  2688. } catch (e) {
  2689. }
  2690. };
  2691. // const triggerPlaying = async () => {
  2692. // await player_.cancelPlayback();
  2693. // this.pauseVideo();
  2694. // this.playVideo();
  2695. // await player_.pauseVideo();
  2696. // await player_.playVideo();
  2697. // };
  2698. const seekToLiveHeadForLiveStream = async () => {
  2699. try {
  2700. audio.isConnected === true && await player_.seekToLiveHead();
  2701. if (audio.isConnected === true && (await player_.isAtLiveHead()) === true) {
  2702. audio.isConnected === true && await player_.seekToStreamTime();
  2703. return true;
  2704. }
  2705. } catch (e) {
  2706. console.log('error_F7', e);
  2707. }
  2708. };
  2709.  
  2710.  
  2711. if(a.includes('error') ){
  2712. if(!media.__publishStatus17__ || media.__publishStatus17__ < 200){
  2713.  
  2714. await player_.clearVideo(); // avoid error in live streaming
  2715. await player_.clearQueue(); // avoid error in live streaming
  2716. await refreshAllStaleEntitiesForNonReadyAudio();
  2717. // await player_.cancelPlayback();
  2718.  
  2719. }
  2720. }else{
  2721.  
  2722.  
  2723.  
  2724. media.__publishStatus17__ = media.__publishStatus17__ || 100;
  2725.  
  2726.  
  2727.  
  2728. if (media.__publishStatus17__ === 100) await refreshAllStaleEntitiesForNonReadyAudio();
  2729. if (media.__publishStatus17__ === 100 && audio.duration > 0 && player_.getPlayerState() === 3) {
  2730. media.__publishStatus17__ = 200
  2731. // await refreshAllStaleEntitiesForNonReadyAudio();
  2732. await player_.cancelPlayback();
  2733. await this.pauseVideo();
  2734. // this.playVideo();
  2735. // await player_.pauseVideo();
  2736. await player_.playVideo();
  2737. await seekToLiveHeadForLiveStream();
  2738. // fixLiveAudioFn(domMedia0, player_, player_.getPlayerState())
  2739. // skipPause = true;
  2740. // skipVisibility = true;
  2741. // player_.cancelPlayback();
  2742. // player_.pauseVideo();
  2743. // player_.playVideo();
  2744. // skipPause = false;
  2745. // skipVisibility = false;
  2746. }
  2747. if (a === 'onLoadedMetadata' && media.__publishStatus17__ === 200) media.__publishStatus17__ = 201;
  2748. if (a === 'videoelementevent' && b.type === 'loadedmetadata' && media.__publishStatus17__ === 201) media.__publishStatus17__ = 202;
  2749. if (a === 'videoelementevent' && b.type === 'progress' && media.__publishStatus17__ === 202) {
  2750. media.__publishStatus17__ = 203;
  2751. window.debug_mfk = this;
  2752. window.debug_mfp = player_;
  2753. // (async ()=>{
  2754. // await timelineResolve();
  2755. // const domMedia = Object.values(this.mediaElement).filter(e=>e instanceof HTMLMediaElement);
  2756. // if(domMedia.length === 1){
  2757. // const domMedia0 = domMedia[0]
  2758. // if(domMedia0.duration >0 && domMedia0.readyState >= 4){
  2759. // await timelineResolve();
  2760. // console.log(939, domMedia0, domMedia0.paused, domMedia0.duration, domMedia0.readyState)
  2761. // this.pauseVideo();
  2762. // await timelineResolve();
  2763. // this.playVideo();
  2764. // }
  2765. // // this.mediaElement.pause();
  2766. // // this.mediaElement.play();
  2767. // }
  2768. // })();
  2769. }
  2770. if (media.__publishStatus17__ === 203 && audio && audio.readyState === 1) {
  2771. media.__publishStatus17__ = 204;
  2772. // await timelineResolve();
  2773. // await player_.cancelPlayback();
  2774. await this.pauseVideo();
  2775. // this.playVideo();
  2776. // await timelineResolve();
  2777. // await player_.pauseVideo();
  2778. await player_.playVideo();
  2779. // await timelineResolve();
  2780. await seekToLiveHeadForLiveStream();
  2781. }
  2782. if (media.__publishStatus17__ < 300 && media.__publishStatus17__ >= 200 && a === 'videoelementevent' && b.type==='timeupdate' && !audio.paused && audio.readyState >= 4 && audio.duration > 0) {
  2783. media.__publishStatus17__ = 300;
  2784. if(!player_.isAtLiveHead()) await seekToLiveHeadForLiveStream();
  2785. }
  2786.  
  2787. }
  2788.  
  2789.  
  2790. publishStatus = media.__publishStatus17__;
  2791.  
  2792. if (debugFlg001) console.log('gkps0 publish | ' + publishStatus, a, printObject(b))
  2793.  
  2794. }
  2795. }
  2796. gkp.publish = function(a,b){
  2797.  
  2798. this.publish33(a,b);
  2799. return this.publish48.apply(this, arguments);
  2800. }
  2801.  
  2802. // console.log(23488)
  2803.  
  2804. })();
  2805.  
  2806. })();
  2807.  
  2808.  
  2809. }
  2810.  
  2811. const getVideoIdByURL = () => {
  2812. // It's almost certainly going to stay at 11 characters. The individual characters come from a set of 64 possibilities (A-Za-z0-9_-).
  2813. // base64 form; 26+26+10+2; 64^len
  2814. // Math.pow(64,11) = 73786976294838210000
  2815.  
  2816. const url = new URL(location.href);
  2817. let m;
  2818.  
  2819. if (m = /^\/watch\?v=([A-Za-z0-9_-]+)/.exec(`${url.pathname}?v=${url.searchParams.get('v')}`)) return `${m[1]}`;
  2820. if (m = /^\/live\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`;
  2821.  
  2822. if (m = /^\/embed\/live_stream\?channel=([A-Za-z0-9_-]+)/.exec(`${url.pathname}?channel=${url.searchParams.get('channel')}`)) return `L:${m[1]}`;
  2823. if (m = /^\/embed\/([A-Za-z0-9_-]+)/.exec(url.pathname)) return `${m[1]}`;
  2824.  
  2825. if (m = /^\/channel\/([A-Za-z0-9_-]+)\/live\b/.exec(url.pathname)) return `L:${m[1]}`;
  2826. if (url.hostname === 'youtu.be' && (m = /\/([A-Za-z0-9_-]+)/.exec(url.pathname))) return `${m[1]}`;
  2827.  
  2828. return '';
  2829.  
  2830. };
  2831.  
  2832. const getVideoIdByElement = ()=>{
  2833. const videoIdElements = [...document.querySelectorAll('[video-id]')].filter(v => !v.closest('[hidden]'));
  2834. const videoId = videoIdElements.length > 0 ? videoIdElements[0].getAttribute('video-id') : null;
  2835. return videoId || '';
  2836. };
  2837.  
  2838. const getEnableValue = async ()=>{
  2839. const videoId = getVideoIdByURL() || getVideoIdByElement();
  2840. const siteVal = videoId ? await GM.getValue(`isEnable_aWsjF_${videoId}`, null) : null;
  2841. return (siteVal !== null) ? siteVal : await GM.getValue("isEnable_aWsjF", true);
  2842. };
  2843.  
  2844. const setEnableVal = async (val)=>{
  2845. const videoId = getVideoIdByURL() || getVideoIdByElement();
  2846. if (videoId) {
  2847. try {
  2848. const cv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null);
  2849. if (typeof cv === typeof val) await GM.setValue(`isEnable_aWsjF_${videoId}`, val);
  2850. } catch (e) { }
  2851. }
  2852. await GM.setValue("isEnable_aWsjF", val);
  2853. }
  2854.  
  2855. const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? await getEnableValue() : null;
  2856. if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
  2857. if (isEnable) {
  2858. const element = document.createElement('button');
  2859. element.setAttribute('onclick', createHTML(`(${pageInjectionCode})()`));
  2860. element.click();
  2861. }
  2862.  
  2863. GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
  2864. await setEnableVal(!isEnable);
  2865. await GM.setValue('lastCheck_bWsm5', Date.now());
  2866. document.documentElement.setAttribute('forceRefresh032', '');
  2867. location.reload();
  2868. });
  2869.  
  2870. let messageCount = 0;
  2871. let busy = false;
  2872. window.addEventListener('message', (evt) => {
  2873.  
  2874. const v = ((evt || 0).data || 0).ZECxh;
  2875. if (typeof v === 'boolean') {
  2876. if (messageCount > 1e9) messageCount = 9;
  2877. const t = ++messageCount;
  2878. if (v && isEnable) {
  2879. requestAnimationFrame(async () => {
  2880. if (t !== messageCount) return;
  2881. if (busy) return;
  2882. busy = true;
  2883. if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
  2884. await setEnableVal(!isEnable);
  2885. await GM.setValue('lastCheck_bWsm5', Date.now());
  2886. document.documentElement.setAttribute('forceRefresh032', '');
  2887. location.reload();
  2888. }
  2889. busy = false;
  2890. });
  2891. }
  2892. }
  2893.  
  2894. });
  2895.  
  2896.  
  2897. const pLoad = new Promise(resolve => {
  2898. if (document.readyState !== 'loading') {
  2899. resolve();
  2900. } else {
  2901. window.addEventListener("DOMContentLoaded", resolve, false);
  2902. }
  2903. });
  2904.  
  2905.  
  2906. function contextmenuInfoItemAppearedFn(target) {
  2907.  
  2908. const btn = target.closest('.ytp-menuitem[role="menuitem"]');
  2909. if (!btn) return;
  2910. if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return;
  2911. document.documentElement.classList.add('with-audio-only-toggle-btn');
  2912. const newBtn = btn.cloneNode(true)
  2913. newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  2914. newBtn.classList.add('audio-only-toggle-btn');
  2915. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  2916. newBtn.addEventListener('click', async (evt) => {
  2917. try {
  2918. evt.stopPropagation();
  2919. evt.stopImmediatePropagation();
  2920. } catch (e) { }
  2921. await setEnableVal(!isEnable);
  2922. await GM.setValue('lastCheck_bWsm5', Date.now());
  2923. document.documentElement.setAttribute('forceRefresh032', '');
  2924. location.reload();
  2925. });
  2926. let t;
  2927. let h = 0;
  2928. t = btn.closest('.ytp-panel-menu[style*="height"]');
  2929. if (t) t.style.height = t.scrollHeight + 'px';
  2930. t = btn.closest('.ytp-panel[style*="height"]');
  2931. if (t) t.style.height = (h = t.scrollHeight) + 'px';
  2932. t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]');
  2933. if (t && h > 0) t.style.height = h + 'px';
  2934. }
  2935.  
  2936.  
  2937. function mobileMenuItemAppearedFn(target) {
  2938.  
  2939. const btn = target.closest('ytm-menu-item');
  2940. if (!btn) return;
  2941. if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return;
  2942. document.documentElement.classList.add('with-audio-only-toggle-btn');
  2943. const newBtn = btn.cloneNode(true);
  2944. newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  2945. newBtn.classList.add('audio-only-toggle-btn');
  2946. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  2947. newBtn.addEventListener('click', async (evt) => {
  2948. try {
  2949. evt.stopPropagation();
  2950. evt.stopImmediatePropagation();
  2951. } catch (e) { }
  2952. await setEnableVal(!isEnable);
  2953. await GM.setValue('lastCheck_bWsm5', Date.now());
  2954. document.documentElement.setAttribute('forceRefresh032', '');
  2955. location.reload();
  2956. });
  2957. }
  2958.  
  2959. const lastEntry = (arr) => {
  2960. return arr.length > 0 ? arr[arr.length - 1] : null;
  2961. }
  2962.  
  2963. function mobileMenuItemAppearedV2Fn(target) {
  2964.  
  2965. const btn = target.closest('yt-list-item-view-model');
  2966. if (!(btn instanceof HTMLElement)) return;
  2967. if (btn.parentNode.querySelector('yt-list-item-view-model.audio-only-toggle-btn')) return;
  2968. const parentNode = btn.closest('player-settings-menu');
  2969. if(!parentNode) return;
  2970. let qt = 1E9;
  2971. let targetBtnO = lastEntry([...parentNode.getElementsByTagName(btn.nodeName)].filter(e => e.parentElement === btn.parentElement).map((elm) => {
  2972. const count = elm.getElementsByTagName('*').length;
  2973. if (count < qt) qt = count;
  2974. return {
  2975. elm: elm,
  2976. count: count
  2977. }
  2978. }).filter((o) => o.count === qt));
  2979.  
  2980. const targetBtn = targetBtnO && targetBtnO.elm instanceof HTMLElement ? targetBtnO.elm : btn;
  2981.  
  2982.  
  2983. const newBtn = targetBtn.cloneNode(true);
  2984. if(newBtn instanceof HTMLElement){
  2985. document.documentElement.classList.add('with-audio-only-toggle-btn');
  2986.  
  2987. let newBtnContentElm = newBtn;
  2988. let layerCN = 8;
  2989. while (newBtnContentElm.childElementCount === 1 && layerCN--) {
  2990. newBtnContentElm = newBtnContentElm.firstElementChild;
  2991. }
  2992. if (!(newBtnContentElm instanceof HTMLElement)) newBtnContentElm = newBtn;
  2993. let t;
  2994. if (t = lastEntry(newBtnContentElm.querySelectorAll('span[role="text"]'))) {
  2995. newBtnContentElm = t;
  2996. newBtnContentElm.classList.add('audio-only-toggle-btn-content2');
  2997. } else if (t = lastEntry(newBtnContentElm.querySelectorAll('[role="text"]'))) {
  2998. newBtnContentElm = t;
  2999. newBtnContentElm.classList.add('audio-only-toggle-btn-content2');
  3000. } else if (t = lastEntry(newBtnContentElm.querySelectorAll('span'))) {
  3001. newBtnContentElm = t;
  3002. newBtnContentElm.classList.add('audio-only-toggle-btn-content2');
  3003. } else if (t = lastEntry(newBtnContentElm.querySelector('.yt-core-attributed-string'))) {
  3004. newBtnContentElm = t;
  3005. newBtnContentElm.classList.add('audio-only-toggle-btn-content2');
  3006. }
  3007. newBtnContentElm.textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  3008. newBtn.classList.add('audio-only-toggle-btn');
  3009. newBtnContentElm.classList.add('audio-only-toggle-btn-content');
  3010. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  3011. newBtn.addEventListener('click', async (evt) => {
  3012. try {
  3013. evt.stopPropagation();
  3014. evt.stopImmediatePropagation();
  3015. } catch (e) { }
  3016. await setEnableVal(!isEnable);
  3017. await GM.setValue('lastCheck_bWsm5', Date.now());
  3018. document.documentElement.setAttribute('forceRefresh032', '');
  3019. location.reload();
  3020. });
  3021. const contentWrapper = newBtn.closest('#content-wrapper');
  3022. if (contentWrapper) {
  3023. contentWrapper.style.height = 'unset';
  3024. contentWrapper.style.maxHeight = 'unset';
  3025. }
  3026. }
  3027. }
  3028.  
  3029. pLoad.then(() => {
  3030.  
  3031. document.addEventListener('animationstart', (evt) => {
  3032. const animationName = evt.animationName;
  3033. if (!animationName) return;
  3034.  
  3035. if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target);
  3036. if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target);
  3037. if (animationName === 'mobileMenuItemAppearedV2') mobileMenuItemAppearedV2Fn(evt.target);
  3038.  
  3039. }, true);
  3040.  
  3041. const cssForEnabled = isEnable ? `
  3042.  
  3043. .html5-video-player {
  3044. background-color: black;
  3045. }
  3046.  
  3047. [style*="--audio-only-thumbnail-image"]{
  3048. background-image: var(--audio-only-thumbnail-image);
  3049. object-fit: contain;
  3050. background-position: center;
  3051. background-size: contain;
  3052. background-repeat: no-repeat;
  3053. }
  3054. .html5-video-player.ended-mode [style*="--audio-only-thumbnail-image"]{
  3055. background-image: none;
  3056. }
  3057.  
  3058. .html5-video-player.ytp-ce-shown .html5-video-container {
  3059. opacity: 0.5;
  3060. transition: opacity 0.5s;
  3061. }
  3062.  
  3063. ytd-video-preview #media-container div#player-container,
  3064. ytd-video-preview #media-container div#thumbnail-container{
  3065. transition: initial !important;
  3066. transition-duration:0ms !important;
  3067. transition-delay:0ms !important;
  3068. }
  3069. ytd-video-preview #media-container div#thumbnail-container{
  3070. /* pointer-events:none !important; */
  3071. opacity:0;
  3072. /* z-index:-1; */
  3073. }
  3074. ytd-video-preview #media-container div#player-container,
  3075. ytd-video-preview #media-container div#inline-preview-player{
  3076. background-color:transparent !important;
  3077. background-image:none !important;
  3078. }
  3079.  
  3080. #movie_player > .html5-video-container:not(:empty) {
  3081. box-sizing: border-box;
  3082. height: 100%;
  3083. }
  3084.  
  3085. #movie_player [style*="--audio-only-thumbnail-image"] ~ .ytp-cued-thumbnail-overlay > .ytp-cued-thumbnail-overlay-image[style*="background-image"] {
  3086. opacity: 0;
  3087. }
  3088.  
  3089. #movie_player [style*="--audio-only-thumbnail-image"]::before {
  3090. content: '';
  3091. display: block;
  3092. position: absolute;
  3093. left: 0;
  3094. top: 0;
  3095. bottom: 0;
  3096. right: 0;
  3097. /* background: transparent; */
  3098.  
  3099.  
  3100. /* We use multiple backgrounds: one gradient per side */
  3101. background:
  3102. /* Left border gradient */
  3103. linear-gradient(to right, rgba(0,0,0,0.4), transparent) left center,
  3104. /* Right border gradient */
  3105. linear-gradient(to left, rgba(0,0,0,0.4), transparent) right center,
  3106. /* Top border gradient */
  3107. linear-gradient(to bottom, rgba(0,0,0,0.4), transparent) center top,
  3108. /* Bottom border gradient */
  3109. linear-gradient(to top, rgba(0,0,0,0.4), transparent) center bottom;
  3110. /* Prevents repetition of gradients */
  3111. background-repeat: no-repeat;
  3112. /* Set the size of each gradient "border" */
  3113. background-size:
  3114. 12% 100%, /* left border width and full height */
  3115. 12% 100%, /* right border width and full height */
  3116. 100% 12%, /* top border full width and small height */
  3117. 100% 12%; /* bottom border full width and small height */
  3118. /* Optional: a base background color inside the element */
  3119. /* background-color: #fff; */
  3120. /* background-color: var(--blinker-fmw83-bgc, transparent); */
  3121.  
  3122. opacity: var(--fmw83-opacity, 1);
  3123.  
  3124. pointer-events: none !important;
  3125. z-index:-1;
  3126.  
  3127. }
  3128.  
  3129. /*
  3130. @keyframes blinker-fmw83 {
  3131. 0%, 60%, 100% {
  3132. opacity: 1;
  3133. }
  3134. 30% {
  3135. opacity: 0.96;
  3136. }
  3137. }
  3138. */
  3139. #movie_player.playing-mode [style*="--audio-only-thumbnail-image"]{
  3140. /* animation: blinker-fmw83 1.74s linear infinite; */
  3141. --fmw83-opacity: 0.6;
  3142. }
  3143.  
  3144.  
  3145. `: "";
  3146.  
  3147. const style = document.createElement('style');
  3148. style.id = 'fm9v0';
  3149. style.textContent = `
  3150.  
  3151. ${cssForEnabled}
  3152.  
  3153. @keyframes mobileMenuItemAppeared {
  3154. 0% {
  3155. background-position-x: 3px;
  3156. }
  3157. 100% {
  3158. background-position-x: 4px;
  3159. }
  3160. }
  3161.  
  3162. @keyframes mobileMenuItemAppearedV2 {
  3163. 0% {
  3164. background-position-x: 3px;
  3165. }
  3166. 100% {
  3167. background-position-x: 4px;
  3168. }
  3169. }
  3170. ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type {
  3171. animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards;
  3172. }
  3173.  
  3174. player-settings-menu > yt-list-item-view-model:last-of-type {
  3175. animation: mobileMenuItemAppearedV2 1ms linear 0s 1 normal forwards;
  3176. }
  3177.  
  3178.  
  3179. player-settings-menu .audio-only-toggle-btn-content {
  3180. padding: 14px 24px;
  3181. box-sizing: border-box;
  3182. font-size: 130%;
  3183. }
  3184.  
  3185. player-settings-menu .audio-only-toggle-btn-content2 {
  3186. padding: 0;
  3187. box-sizing: border-box;
  3188. font-size: inherit;
  3189. }
  3190.  
  3191.  
  3192. @keyframes contextmenuInfoItemAppeared {
  3193. 0% {
  3194. background-position-x: 3px;
  3195. }
  3196. 100% {
  3197. background-position-x: 4px;
  3198. }
  3199. }
  3200. .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{
  3201. animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards;
  3202. }
  3203. #confirmDialog794 {
  3204. z-index:999999 !important;
  3205. display: none;
  3206. /* Hidden by default */
  3207. position: fixed;
  3208. /* Stay in place */
  3209. z-index: 1;
  3210. /* Sit on top */
  3211. left: 0;
  3212. top: 0;
  3213. width: 100%;
  3214. /* Full width */
  3215. height: 100%;
  3216. /* Full height */
  3217. overflow: auto;
  3218. /* Enable scroll if needed */
  3219. background-color: rgba(0,0,0,0.4);
  3220. /* Black w/ opacity */
  3221. }
  3222. #confirmDialog794 .confirm-box {
  3223. position:relative;
  3224. color: black;
  3225. z-index:999999 !important;
  3226. background-color: #fefefe;
  3227. margin: 15% auto;
  3228. /* 15% from the top and centered */
  3229. padding: 20px;
  3230. border: 1px solid #888;
  3231. width: 30%;
  3232. /* Could be more or less, depending on screen size */
  3233. box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  3234. }
  3235. #confirmDialog794 .confirm-buttons {
  3236. text-align: right;
  3237. }
  3238. #confirmDialog794 button {
  3239. margin-left: 10px;
  3240. }
  3241.  
  3242. `
  3243. document.head.appendChild(style);
  3244.  
  3245. });
  3246.  
  3247.  
  3248. const pNavigateFinished = new Promise(resolve => {
  3249. document.addEventListener('yt-navigate-finish', resolve, true);
  3250. });
  3251.  
  3252. pNavigateFinished.then(() => {
  3253. const inputs = document.querySelectorAll('#masthead input[type="text"][name]');
  3254.  
  3255. let lastInputTextValue = null;
  3256. let busy = false;
  3257. let disableMonitoring = false;
  3258. const setGV = async (val)=>{
  3259.  
  3260. const videoId = getVideoIdByURL() || getVideoIdByElement();
  3261. if (videoId) {
  3262. const cgv = await GM.getValue(`isEnable_aWsjF_${videoId}`, null);
  3263. if (cgv !== val || isEnable !== val) {
  3264. disableMonitoring = true;
  3265. await GM.setValue(`isEnable_aWsjF_${videoId}`, val);
  3266. await GM.setValue('lastCheck_bWsm5', Date.now());
  3267. document.documentElement.setAttribute('forceRefresh032', '');
  3268. location.reload();
  3269. }
  3270.  
  3271. }
  3272. }
  3273. const checkTextChangeF = async (evt) => {
  3274. busy = false;
  3275. const inputElem = (evt || 0).target;
  3276. if (inputElem instanceof HTMLInputElement && !disableMonitoring) {
  3277. const cv = inputElem.value;
  3278. if (cv === lastInputTextValue) return;
  3279. lastInputTextValue = cv;
  3280. if (cv === 'vvv') {
  3281.  
  3282. await setGV(false);
  3283.  
  3284. } else if (cv === 'aaa') {
  3285.  
  3286. await setGV(true);
  3287.  
  3288. }
  3289. }
  3290. }
  3291. const checkTextChange = (evt) => {
  3292. if (busy) return;
  3293. busy = true;
  3294. Promise.resolve(evt).then(checkTextChangeF)
  3295. };
  3296. for (const input of inputs) {
  3297. input.addEventListener('input', checkTextChange, false);
  3298. input.addEventListener('keydown', checkTextChange, false);
  3299. input.addEventListener('keyup', checkTextChange, false);
  3300. input.addEventListener('keypress', checkTextChange, false);
  3301. input.addEventListener('change', checkTextChange, false);
  3302. }
  3303. });
  3304.  
  3305. const autoCleanUpKey = async () => {
  3306.  
  3307. const lastCheck = await GM.getValue('lastCheck_bWsm5', null) || 0;
  3308. if (Date.now() - lastCheck < 16000) return; // 16s
  3309. GM.setValue('lastCheck_bWsm5', Date.now());
  3310. pLoad.then(async () => {
  3311. const rArr = [];
  3312. const arr = await GM.listValues();
  3313. const cv = await GM.getValue("isEnable_aWsjF", null);
  3314. const fn = async (entry) => {
  3315. try {
  3316. if (typeof entry === 'string' && entry.length > 15 && entry.startsWith('isEnable_aWsjF_')) {
  3317. const res = await GM.getValue(entry, null);
  3318. if (typeof res === 'boolean' && res === cv) {
  3319. await GM.deleteValue(entry);
  3320. rArr.push(entry);
  3321. }
  3322. }
  3323. } catch (e) {
  3324. console.warn(e);
  3325. }
  3326. }
  3327. arr.length > 1 && (await Promise.all(arr.map(fn)));
  3328. rArr.length > 0 && console.log('[YouTube Audio Only] autoCleanUpKey', rArr);
  3329. });
  3330. };
  3331.  
  3332. autoCleanUpKey();
  3333.  
  3334.  
  3335. })();
  3336.  
  3337.