YouTube: Audio Only

No Video Streaming

当前为 2024-02-04 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube: Audio Only
  3. // @description No Video Streaming
  4. // @namespace UserScript
  5. // @version 1.6.6
  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. // @run-at document-start
  17. // @license MIT
  18. // @compatible chrome
  19. // @compatible firefox
  20. // @compatible opera
  21. // @compatible edge
  22. // @compatible safari
  23. // @allFrames true
  24. //
  25. // ==/UserScript==
  26.  
  27. (async function () {
  28. 'use strict';
  29.  
  30. /** @type {globalThis.PromiseConstructor} */
  31. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  32.  
  33. if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError");
  34.  
  35. async function confirm(message) {
  36. // Create the HTML for the dialog
  37.  
  38. if (!document.body) return;
  39.  
  40. let dialog = document.getElementById('confirmDialog794');
  41. if (!dialog) {
  42.  
  43. const dialogHTML = `
  44. <div id="confirmDialog794" class="dialog-style" style="display: block;">
  45. <div class="confirm-box">
  46. <p>${message}</p>
  47. <div class="confirm-buttons">
  48. <button id="confirmBtn">Confirm</button>
  49. <button id="cancelBtn">Cancel</button>
  50. </div>
  51. </div>
  52. </div>
  53. `;
  54.  
  55. // Append the dialog to the document body
  56. document.body.insertAdjacentHTML('beforeend', dialogHTML);
  57. dialog = document.getElementById('confirmDialog794');
  58.  
  59. }
  60.  
  61. // Return a promise that resolves or rejects based on the user's choice
  62. return new Promise((resolve) => {
  63. document.getElementById('confirmBtn').onclick = () => {
  64. resolve(true);
  65. cleanup();
  66. };
  67.  
  68. document.getElementById('cancelBtn').onclick = () => {
  69. resolve(false);
  70. cleanup();
  71. };
  72.  
  73. function cleanup() {
  74. dialog && dialog.remove();
  75. dialog = null;
  76. }
  77. });
  78. }
  79.  
  80.  
  81.  
  82. if (location.pathname === '/live_chat' || location.pathname === 'live_chat_replay') return;
  83.  
  84. const kEventListener = (evt) => {
  85. if (document.documentElement.hasAttribute('forceRefresh032')) {
  86. evt.stopImmediatePropagation();
  87. evt.stopPropagation();
  88. }
  89. }
  90. window.addEventListener('beforeunload', kEventListener, false);
  91.  
  92. const pageInjectionCode = function () {
  93.  
  94. const SHOW_VIDEO_STATIC_IMAGE = true;
  95.  
  96. if (typeof AbortSignal === 'undefined') throw new DOMException("Please update your browser.", "NotSupportedError");
  97.  
  98. const URL = window.URL || new Function('return URL')();
  99. const createObjectURL = URL.createObjectURL.bind(URL);
  100.  
  101. /** @type {globalThis.PromiseConstructor} */
  102. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  103.  
  104. const PromiseExternal = ((resolve_, reject_) => {
  105. const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
  106. return class PromiseExternal extends Promise {
  107. constructor(cb = h) {
  108. super(cb);
  109. if (cb === h) {
  110. /** @type {(value: any) => void} */
  111. this.resolve = resolve_;
  112. /** @type {(reason?: any) => void} */
  113. this.reject = reject_;
  114. }
  115. }
  116. };
  117. })();
  118.  
  119.  
  120.  
  121.  
  122.  
  123. const createPipeline = () => {
  124. let pipelineMutex = Promise.resolve();
  125. const pipelineExecution = fn => {
  126. return new Promise((resolve, reject) => {
  127. pipelineMutex = pipelineMutex.then(async () => {
  128. let res;
  129. try {
  130. res = await fn();
  131. } catch (e) {
  132. console.log('error_F1', e);
  133. reject(e);
  134. }
  135. resolve(res);
  136. }).catch(console.warn);
  137. });
  138. };
  139. return pipelineExecution;
  140. }
  141.  
  142. const observablePromise = (proc, timeoutPromise) => {
  143. let promise = null;
  144. return {
  145. obtain() {
  146. if (!promise) {
  147. promise = new Promise(resolve => {
  148. let mo = null;
  149. const f = () => {
  150. let t = proc();
  151. if (t) {
  152. mo.disconnect();
  153. mo.takeRecords();
  154. mo = null;
  155. resolve(t);
  156. }
  157. }
  158. mo = new MutationObserver(f);
  159. mo.observe(document, { subtree: true, childList: true })
  160. f();
  161. timeoutPromise && timeoutPromise.then(() => {
  162. resolve(null)
  163. });
  164. });
  165. }
  166. return promise
  167. }
  168. }
  169. }
  170.  
  171.  
  172. const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  173.  
  174. let setTimeout_ = setTimeout;
  175. let clearTimeout_ = clearTimeout;
  176.  
  177. const delayPn = delay => new Promise((fn => setTimeout_(fn, delay)));
  178.  
  179.  
  180. const mockEvent = (o, elem) => {
  181. o = o || {};
  182. elem = elem || null;
  183. return {
  184. preventDefault: () => { },
  185. stopPropagation: () => { },
  186. stopImmediatePropagation: () => { },
  187. returnValue: true,
  188. target: elem,
  189. srcElement: elem,
  190. defaultPrevented: false,
  191. cancelable: true,
  192. timeStamp: performance.now(),
  193. ...o
  194. }
  195. };
  196.  
  197.  
  198. const generalRegister = (prop, symbol, checker, pg) => {
  199. const objSet = new Set();
  200. let done = false;
  201. const f = (o) => {
  202. const ct = o.constructor;
  203. const proto = ct.prototype;
  204. if (!done && proto && ct !== Function && ct !== Object && checker(proto)) {
  205. done = true;
  206. delete Object.prototype[prop];
  207. objSet.delete(proto);
  208. objSet.delete(o);
  209. for (const obj of objSet) {
  210. obj[prop] = obj[symbol];
  211. delete obj[symbol];
  212. }
  213. objSet.clear();
  214. Object.defineProperty(proto, prop, pg);
  215. return proto;
  216. }
  217. return false;
  218. };
  219. Object.defineProperty(Object.prototype, prop, {
  220. get() {
  221. const p = f(this);
  222. if (p) {
  223. return p[prop];
  224. } else {
  225. return this[symbol];
  226. }
  227. },
  228. set(nv) {
  229. const p = f(this);
  230. if (p) {
  231. p[prop] = nv;
  232. } else {
  233. objSet.add(this);
  234. this[symbol] = nv;
  235. }
  236. return true;
  237. },
  238. enumerable: false,
  239. configurable: true
  240. });
  241.  
  242. };
  243.  
  244. const updateLastActiveTimeAsync = (player_) => {
  245. // TBC
  246. Promise.resolve().then(() => {
  247. if (typeof player_.updateLastActiveTime === 'function') {
  248. player_.updateLastActiveTime();
  249. }
  250. });
  251. };
  252.  
  253. const attachOneTimeEvent = function (eventType, callback) {
  254. let kz = false;
  255. document.addEventListener(eventType, function (evt) {
  256. if (kz) return;
  257. kz = true;
  258. callback(evt);
  259. }, { capture: true, passive: true, once: true });
  260. }
  261.  
  262. function removeTempObjectProp01() {
  263. delete Object.prototype['kevlar_non_watch_unified_player'];
  264. delete Object.prototype['kevlar_unified_player'];
  265. }
  266.  
  267. function ytConfigFix(config__) {
  268. const config_ = config__;
  269.  
  270. if (config_) {
  271.  
  272. const playerKevlar = ((config_ || 0).WEB_PLAYER_CONTEXT_CONFIGS || 0).WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH || 0;
  273.  
  274. if (playerKevlar) {
  275.  
  276. // console.log(322, playerKevlar)
  277. playerKevlar.allowWoffleManagement = false;
  278. playerKevlar.cinematicSettingsAvailable = false;
  279. playerKevlar.showMiniplayerButton = false;
  280. playerKevlar.showMiniplayerUiWhenMinimized = false;
  281. playerKevlar.transparentBackground = false;
  282.  
  283. playerKevlar.enableCsiLogging = false;
  284. playerKevlar.externalFullscreen = false;
  285.  
  286. if (typeof playerKevlar.serializedExperimentFlags === 'string') {
  287. playerKevlar.serializedExperimentFlags = '';
  288. // playerKevlar.serializedExperimentFlags = playerKevlar.serializedExperimentFlags.replace(/[-\w]+=(\[\]|[.-\d]+|[_a-z]+|)(&|$)/g,'').replace(/&$/,'')
  289. }
  290.  
  291. if (typeof playerKevlar.serializedExperimentIds === 'string') {
  292. playerKevlar.serializedExperimentIds = '';
  293. // playerKevlar.serializedExperimentIds = playerKevlar.serializedExperimentIds.replace(/\d+\s*(,\s*|$)/g,'')
  294. }
  295.  
  296. }
  297.  
  298. removeTempObjectProp01();
  299.  
  300. let configs = config_.WEB_PLAYER_CONTEXT_CONFIGS || {};
  301. for (const [key, entry] of Object.entries(configs)) {
  302.  
  303. if (entry && typeof entry.serializedExperimentFlags === 'string') {
  304. // prevent idle playback failure
  305. 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) => {
  306. return a + '00' + '=' + b + c;
  307. });
  308.  
  309. }
  310.  
  311. }
  312.  
  313. const EXPERIMENT_FLAGS = config_.EXPERIMENT_FLAGS;
  314.  
  315. if (EXPERIMENT_FLAGS) {
  316. EXPERIMENT_FLAGS.kevlar_unified_player = true;
  317. EXPERIMENT_FLAGS.kevlar_non_watch_unified_player = true;
  318. }
  319.  
  320.  
  321. const EXPERIMENTS_FORCED_FLAGS = config_.EXPERIMENTS_FORCED_FLAGS;
  322.  
  323. if (EXPERIMENTS_FORCED_FLAGS) {
  324. EXPERIMENTS_FORCED_FLAGS.kevlar_unified_player = true;
  325. EXPERIMENTS_FORCED_FLAGS.kevlar_non_watch_unified_player = true;
  326. }
  327.  
  328. }
  329. }
  330.  
  331. Object.defineProperty(Object.prototype, 'kevlar_non_watch_unified_player', {
  332. get() {
  333. // console.log(501, this.constructor.prototype)
  334. return true;
  335. },
  336. set(nv) {
  337. return true;
  338. },
  339. enumerable: false,
  340. configurable: true
  341. });
  342.  
  343.  
  344. Object.defineProperty(Object.prototype, 'kevlar_unified_player', {
  345. get() {
  346. // console.log(501, this.constructor.prototype)
  347. return true;
  348. },
  349. set(nv) {
  350. return true;
  351. },
  352. enumerable: false,
  353. configurable: true
  354. });
  355.  
  356. let prr = new PromiseExternal();
  357. const prrPipeline = createPipeline();
  358. let stopAndReload = false;
  359.  
  360. let fa = 0;
  361.  
  362. let cv = null;
  363. let durationchangeForMobile = false;
  364. function fixThumbnailURL(src) {
  365. if (typeof src === 'string' && src.length >= 4) {
  366. let m = /\b[a-z0-9]{4,13}\.jpg\b/.exec(src);
  367. if (m && m[0]) {
  368. const t = m[0];
  369. let idx = src.indexOf(t);
  370. let nSrc = idx >= 0 ? src.substring(0, idx + t.length) : '';
  371. return nSrc;
  372. }
  373. }
  374. return src;
  375. }
  376.  
  377. const isDesktopSite = location.origin === 'https://www.youtube.com' && !location.pathname.startsWith('/embed/');
  378.  
  379. const getThumbnailUrlFromThumbnails = (thumbnails) => {
  380.  
  381. let thumbnailUrl = '';
  382. if (thumbnails && thumbnails.length >= 1) {
  383. const arr = thumbnails.map(e => {
  384. return e.url ? [e.width * e.height, e.url] : typeof e === 'string' ? [0, e] : [0, '']
  385. });
  386. arr.sort((a, b) => b[0] - a[0]);
  387. thumbnailUrl = arr[0][1]
  388. if (typeof thumbnailUrl === 'string') {
  389. thumbnailUrl = fixThumbnailURL(thumbnailUrl);
  390. }
  391. }
  392. return thumbnailUrl;
  393. }
  394.  
  395. const pmof = () => {
  396.  
  397. if (SHOW_VIDEO_STATIC_IMAGE) {
  398.  
  399. const medias = [...document.querySelectorAll('ytd-watch-flexy #player .html5-video-container .video-stream.html5-main-video')].filter(e => !e.closest('[hidden]'));
  400. if (medias.length !== 1) return;
  401. const mediaElement = medias[0];
  402.  
  403. const container = mediaElement ? mediaElement.closest('.html5-video-container') : null;
  404. if (!container) return;
  405.  
  406. let thumbnailUrl = '';
  407. const ytdPage = container.closest('ytd-watch-flexy');
  408. if (ytdPage && ytdPage.is === 'ytd-watch-flexy') {
  409. const cnt = insp(ytdPage);
  410. let thumbnails = null;
  411. try {
  412. thumbnails = cnt.polymerController.__data.playerData.videoDetails.thumbnail.thumbnails
  413. // thumbnails = cnt.__data.watchNextData.playerOverlays.playerOverlayRenderer.autoplay.playerOverlayAutoplayRenderer.background.thumbnails
  414. } catch (e) { }
  415.  
  416. thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  417. }
  418.  
  419.  
  420. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  421. container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  422. } else {
  423. container.style.removeProperty('--audio-only-thumbnail-image')
  424. }
  425.  
  426. }
  427.  
  428.  
  429. }
  430. const pmo = new MutationObserver(pmof);
  431.  
  432. isDesktopSite && document.addEventListener('yt-navigate-finish', () => {
  433. const ytdWatchFlexy = document.querySelector('ytd-watch-flexy');
  434. if (ytdWatchFlexy) {
  435. pmo.observe(ytdWatchFlexy, { attributes: true });
  436. ytdWatchFlexy.setAttribute('ytzNavigateFinish', Date.now());
  437. }
  438. });
  439. document.addEventListener('durationchange', (evt) => {
  440. const target = (evt || 0).target;
  441. if (!(target instanceof HTMLMediaElement)) return;
  442. const targetClassList = target.classList || 0;
  443. const isPlayerVideo = typeof targetClassList.contains === 'function' ? targetClassList.contains('video-stream') && targetClassList.contains('html5-main-video') : false;
  444.  
  445. if (durationchangeForMobile || isPlayerVideo) {
  446. if (target.readyState !== 1) {
  447. fa = 1;
  448. } else {
  449. fa = 2;
  450. }
  451. }
  452.  
  453. if (isPlayerVideo) {
  454.  
  455. if (target.readyState === 1 && target.networkState === 2) {
  456. target.__spfgs__ = true;
  457. if (cv) {
  458. cv.resolve();
  459. cv = null;
  460. }
  461. } else {
  462. target.__spfgs__ = false;
  463. }
  464.  
  465. if (isDesktopSite) {
  466. const ytdWatchFlexy = document.querySelector('ytd-watch-flexy');
  467. if (ytdWatchFlexy) {
  468. ytdWatchFlexy.setAttribute('ytzMediaDurationChanged', Date.now());
  469. }
  470. }
  471.  
  472. if (onVideoChangeForMobile) {
  473. onVideoChangeForMobile();
  474. }
  475.  
  476. }
  477. }, true);
  478.  
  479.  
  480.  
  481. // XMLHttpRequest.prototype.open299 = XMLHttpRequest.prototype.open;
  482. /*
  483.  
  484. XMLHttpRequest.prototype.open2 = function(method, url, ...args){
  485.  
  486. if (typeof url === 'string' && url.length > 24 && url.includes('/videoplayback?') && url.replace('?', '&').includes('&source=')) {
  487. if (vcc !== vdd) {
  488. vdd = vcc;
  489. window.postMessage({ ZECxh: url.includes('source=yt_live_broadcast') }, "*");
  490. }
  491. }
  492.  
  493. return this.open299(method, url, ...args)
  494. }*/
  495.  
  496.  
  497.  
  498. // desktop only
  499. // document.addEventListener('yt-page-data-fetched', async (evt) => {
  500.  
  501. // const pageFetchedDataLocal = evt.detail;
  502. // let isLiveNow;
  503. // try {
  504. // isLiveNow = pageFetchedDataLocal.pageData.playerResponse.microformat.playerMicroformatRenderer.liveBroadcastDetails.isLiveNow;
  505. // } catch (e) { }
  506. // window.postMessage({ ZECxh: isLiveNow === true }, "*");
  507.  
  508. // }, false);
  509.  
  510. // return;
  511.  
  512. // let clickLockFn = null;
  513.  
  514.  
  515. let onVideoChangeForMobile = null;
  516.  
  517. let removeBottomOverlayForMobile = null;
  518.  
  519. let clickLockFn = null;
  520. let clickTarget = null;
  521. if (location.origin === 'https://m.youtube.com') {
  522.  
  523. EventTarget.prototype.addEventListener322 = EventTarget.prototype.addEventListener;
  524.  
  525. const dummyFn = () => { };
  526. EventTarget.prototype.addEventListener = function (evt, fn, opts) {
  527.  
  528. let hn = fn;
  529.  
  530. // if (evt === 'player-error') {
  531. // } else if (evt === 'player-detailed-error') {
  532. // } else if (evt === 'video-data-change') {
  533. // } else if (evt === 'player-state-change') {
  534. // } else
  535. if (evt === 'player-autonav-pause' || evt === 'visibilitychange') {
  536. evt += 'y'
  537. fn = dummyFn;
  538. } else if (evt === 'click' && this.id === 'movie_player') {
  539. clickLockFn = fn;
  540. clickTarget = this;
  541. }
  542. return this.addEventListener322(evt, hn, opts)
  543.  
  544. }
  545.  
  546. }
  547.  
  548.  
  549.  
  550. (() => {
  551.  
  552. XMLHttpRequest = (() => {
  553. const XMLHttpRequest_ = XMLHttpRequest;
  554. if ('__xmMc8__' in XMLHttpRequest_.prototype) return XMLHttpRequest_;
  555. const url0 = createObjectURL(new Blob([], { type: 'text/plain' }));
  556. const c = class XMLHttpRequest extends XMLHttpRequest_ {
  557. constructor(...args) {
  558. super(...args);
  559. }
  560. open(method, url, ...args) {
  561. let skip = false;
  562. if (!url || typeof url !== 'string') skip = true;
  563. else if (typeof url === 'string') {
  564. let turl = url[0] === '/' ? `.youtube.com${url}` : `${url}`;
  565. if (turl.includes('googleads') || turl.includes('doubleclick.net')) {
  566. skip = true;
  567. } else if (turl.includes('.youtube.com/pagead/')) {
  568. skip = true;
  569. } else if (turl.includes('.youtube.com/ptracking')) {
  570. skip = true;
  571. } else if (turl.includes('.youtube.com/api/stats/')) { // /api/stats/
  572. // skip = true; // for user activity logging e.g. watched videos
  573. } else if (turl.includes('play.google.com/log')) {
  574. skip = true;
  575. } else if (turl.includes('.youtube.com//?')) { // //?cpn=
  576. skip = true;
  577. }
  578. }
  579. if (!skip) {
  580. this.__xmMc8__ = 1;
  581. return super.open(method, url, ...args);
  582. } else {
  583. this.__xmMc8__ = 2;
  584. return super.open('GET', url0);
  585. }
  586. }
  587. send(...args) {
  588. if (this.__xmMc8__ === 1) {
  589. return super.send(...args);
  590. } else if (this.__xmMc8__ === 2) {
  591. return super.send();
  592. } else {
  593. console.log('xhr warning');
  594. return super.send(...args);
  595. }
  596. }
  597. }
  598. c.prototype.__xmMc8__ = 0;
  599. return c;
  600. })();
  601.  
  602. const s7 = Symbol();
  603. const f7 = () => true;
  604.  
  605. !window.canRetry9048 && generalRegister('canRetry', s7, (p) => {
  606. 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'
  607. }, {
  608. get() {
  609. if ('logger' in this && 'policy' in this && 'xhr' && this) {
  610. 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"
  611. // OKAY !
  612. console.log('canRetry05 - ', this.errorMessage)
  613. return f7;
  614. }
  615. // console.log(this)
  616. console.log('canRetry02 - ', this.errorMessage, this)
  617. } else {
  618. console.log('canRetry ERR - ', this.errorMessage)
  619. }
  620. return this[s7];
  621. },
  622. set(nv) {
  623. this[s7] = nv;
  624. return true;
  625. },
  626. enumerable: false,
  627. configurable: true
  628. });
  629. window.canRetry9048 = 1;
  630.  
  631. })();
  632.  
  633. if (location.origin === 'https://www.youtube.com') {
  634.  
  635. if (location.pathname.startsWith('/embed/')) {
  636.  
  637. const ytEmbedReady = observablePromise(() => document.querySelector('#player > .ytp-embed')).obtain();
  638.  
  639. const embedConfigFix = async () => {
  640. while (true) {
  641. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  642. if (config_) {
  643. ytConfigFix(config_);
  644. break;
  645. }
  646. await delayPn(60);
  647. }
  648. };
  649.  
  650. ytEmbedReady.then(async (embedPlayer) => {
  651.  
  652. embedConfigFix();
  653.  
  654. const player_ = embedPlayer;
  655. // console.log(player_)
  656.  
  657. const asyncStateChange = async (audio, k) => {
  658. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  659. try {
  660. if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  661. } catch (e) {
  662. }
  663. };
  664. const triggerPlaying = async () => {
  665. await player_.pauseVideo();
  666. await player_.playVideo();
  667. };
  668. const seekToLiveHeadForLiveStream = async () => {
  669. try {
  670. await player_.seekToLiveHead();
  671. if ((await player_.isAtLiveHead()) === true) {
  672. await player_.seekToStreamTime();
  673. return true;
  674. }
  675. } catch (e) {
  676. console.log('error_F3',e);
  677. }
  678. };
  679. const fixLiveAudioFn = async () => {
  680. if (audio.paused === true) {
  681. await player_.clearVideo(); // avoid error in live streaming
  682. await player_.clearQueue(); // avoid error in live streaming
  683. await delayPn(300);
  684. for (let i = 0; i < 3; i++) {
  685. if (audio.readyState === 0) {
  686. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  687. }
  688. }
  689. if (k === -1) {
  690. await refreshAllStaleEntitiesForNonReadyAudio();
  691. } else if (k === 3) {
  692. while (audio.readyState === 0) {
  693. await refreshAllStaleEntitiesForNonReadyAudio();
  694. await triggerPlaying();
  695. await delayPn(300);
  696. }
  697. }
  698. } else if (audio.paused === false) {
  699. if (!player_.isAtLiveHead()) {
  700. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  701. }
  702. while (audio.readyState === 0) {
  703. await refreshAllStaleEntitiesForNonReadyAudio();
  704. await triggerPlaying();
  705. await delayPn(300);
  706. }
  707. if (!player_.isAtLiveHead()) {
  708. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  709. }
  710. await refreshAllStaleEntitiesForNonReadyAudio();
  711. if (audio.readyState > 0 && audio.paused === true) {
  712. await triggerPlaying();
  713. }
  714. }
  715. }
  716. try {
  717. const ns23 = audio.networkState == 2 || audio.networkState == 3;
  718. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  719. await delayPn(200);
  720. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  721. await fixLiveAudioFn();
  722. }
  723. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  724. await seekToLiveHeadForLiveStream();
  725. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  726. await delayPn(60);
  727. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  728. await fixLiveAudioFn();
  729. }
  730. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  731. await seekToLiveHeadForLiveStream();
  732. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  733. await delayPn(60);
  734. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  735. await fixLiveAudioFn();
  736. }
  737. }
  738.  
  739. } catch (e) {
  740. console.log('error_F4', e)
  741. }
  742.  
  743. };
  744.  
  745. // console.log(299, player_)
  746. const _onPlayerStateChange = (k) => {
  747. try {
  748. if (typeof k === 'number' && k === player_.getPlayerState()) {
  749.  
  750. const audio = document.querySelector('#player audio.video-stream.html5-main-video');
  751. if (audio) asyncStateChange(audio, k);
  752. }
  753. } catch (e) {
  754. console.log('error_F5', e)
  755. }
  756. };
  757.  
  758. player_.addEventListener('onStateChange', _onPlayerStateChange);
  759. const state0 = player_.getPlayerState();
  760. if (typeof state0 === 'number') {
  761. _onPlayerStateChange(state0);
  762. }
  763.  
  764. player_.addEventListener('onVideoProgress', () => {
  765. updateLastActiveTimeAsync(player_);
  766. });
  767.  
  768. // console.log(1231)
  769.  
  770. if (SHOW_VIDEO_STATIC_IMAGE) {
  771.  
  772. let displayImage = '';
  773. let html5Container = null;
  774.  
  775.  
  776. const moviePlayer = document.querySelector('#movie_player .html5-video-container .video-stream.html5-main-video');
  777. if (moviePlayer) {
  778. html5Container = moviePlayer.closest('.html5-video-container');
  779. }
  780.  
  781. if (html5Container) {
  782.  
  783. const overlayImage = document.querySelector('#movie_player .ytp-cued-thumbnail-overlay-image[style]');
  784. if (overlayImage) {
  785.  
  786. const cStyle = window.getComputedStyle(overlayImage);
  787. const cssImageValue = cStyle.backgroundImage;
  788. if (cssImageValue && typeof cssImageValue === 'string' && cssImageValue.startsWith('url(')) {
  789. displayImage = cssImageValue;
  790.  
  791. }
  792.  
  793. }
  794.  
  795. if (!displayImage) {
  796.  
  797. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  798. let embedded_player_response = null;
  799. if (config_) {
  800. embedded_player_response = ((config_.PLAYER_VARS || 0).embedded_player_response || 0)
  801. }
  802. if (embedded_player_response && typeof embedded_player_response === 'string') {
  803.  
  804. let idx1 = embedded_player_response.indexOf('"defaultThumbnail"');
  805. let idx2 = idx1 >= 0 ? embedded_player_response.lastIndexOf('"defaultThumbnail"') : -1;
  806.  
  807. if (idx1 === idx2 && idx1 > 0) {
  808.  
  809. let bk = 0;
  810. let j = -1;
  811. for (let i = idx1; i < embedded_player_response.length; i++) {
  812. if (i > idx1 + 40 && bk === 0) {
  813. j = i;
  814. break;
  815. }
  816. let t = embedded_player_response.charAt(i);
  817. if (t === '{') bk++;
  818. else if (t === '}') bk--;
  819. }
  820.  
  821. if (j > idx1) {
  822.  
  823. let defaultThumbnailString = embedded_player_response.substring(idx1, j);
  824. let defaultThumbnailObject = null;
  825.  
  826. try {
  827. defaultThumbnailObject = JSON.parse(`{${defaultThumbnailString}}`);
  828.  
  829. } catch (e) { }
  830.  
  831. const thumbnails = ((defaultThumbnailObject.defaultThumbnail || 0).thumbnails || 0);
  832.  
  833. if (thumbnails && thumbnails.length >= 1) {
  834.  
  835. let thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  836.  
  837. if (thumbnailUrl && thumbnailUrl.length > 3) {
  838. displayImage = `url(${thumbnailUrl})`;
  839. }
  840. }
  841. }
  842.  
  843. }
  844.  
  845.  
  846. }
  847.  
  848.  
  849. }
  850.  
  851. if (displayImage) {
  852.  
  853. html5Container.style.setProperty('--audio-only-thumbnail-image', `${displayImage}`);
  854. } else {
  855. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  856. }
  857.  
  858. }
  859.  
  860.  
  861. }
  862.  
  863. })
  864.  
  865.  
  866. } else {
  867.  
  868. attachOneTimeEvent('yt-action', () => {
  869. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  870. ytConfigFix(config_);
  871. });
  872.  
  873. const setupAudioPlaying = (player00_) => {
  874. const player_ = player00_;
  875. if (!player_) return;
  876. if (player_.__audio544__) return;
  877. player_.__audio544__ = 1;
  878. // console.log(1233, player_)
  879. let ytdPlayerElement = null;
  880.  
  881. const stopAndReloadFn = async () => {
  882. let isLive = false;
  883. if (location.pathname === '/watch') {
  884. const liveBtn = document.querySelector('.ytp-live-badge.ytp-button');
  885. try {
  886. if (liveBtn && !liveBtn.closest('[hidden]') && (liveBtn.textContent || '').trim().length > 0) {
  887. isLive = true;
  888. }
  889. } catch (e) { }
  890. }
  891. if (isLive) {
  892. player_.destroy();
  893. location.replace(location.href);
  894. await delayPn(8000);
  895. } else {
  896. // await player_.stopVideo();
  897. // await player_.updateVideoData();
  898. // try{
  899. // await player_.refreshAllStaleEntities();
  900. // }catch(e){}
  901. // await player_.playVideo();
  902. }
  903. };
  904. const asyncStateChange = async (audio, k) => {
  905.  
  906. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  907. try {
  908. if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  909. } catch (e) {
  910. }
  911. };
  912. const triggerPlaying = async () => {
  913. await player_.cancelPlayback();
  914. await player_.pauseVideo();
  915. await player_.playVideo();
  916. };
  917. const seekToLiveHeadForLiveStream = async () => {
  918. try {
  919. await player_.seekToLiveHead();
  920. if ((await player_.isAtLiveHead()) === true) {
  921. await player_.seekToStreamTime();
  922. return true;
  923. }
  924. } catch (e) {
  925. console.log('error_F7', e);
  926. }
  927. };
  928. const fixLiveAudioFn = async () => {
  929. if (stopAndReload) {
  930. stopAndReload = false;
  931. await stopAndReloadFn();
  932. }
  933. if (audio.paused === true) {
  934. await player_.clearVideo(); // avoid error in live streaming
  935. await player_.clearQueue(); // avoid error in live streaming
  936. await delayPn(300);
  937. for (let i = 0; i < 3; i++) {
  938. if (audio.readyState === 0) {
  939. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  940. }
  941. }
  942. if (k === -1) {
  943. await refreshAllStaleEntitiesForNonReadyAudio();
  944. } else if (k === 3) {
  945. while (audio.readyState === 0) {
  946. await refreshAllStaleEntitiesForNonReadyAudio();
  947. await triggerPlaying();
  948. await delayPn(300);
  949. }
  950. }
  951. } else if (audio.paused === false) {
  952. if (!player_.isAtLiveHead()) {
  953. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  954. }
  955. while (audio.readyState === 0) {
  956. await refreshAllStaleEntitiesForNonReadyAudio();
  957. await triggerPlaying();
  958. await delayPn(300);
  959. }
  960. if (!player_.isAtLiveHead()) {
  961. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  962. }
  963. await refreshAllStaleEntitiesForNonReadyAudio();
  964. if (audio.readyState > 0 && audio.paused === true) {
  965. await triggerPlaying();
  966. }
  967. }
  968. }
  969. try {
  970.  
  971. const ns23 = audio.networkState == 2 || audio.networkState == 3;
  972. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  973. await delayPn(200);
  974. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  975. await fixLiveAudioFn();
  976. }
  977. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  978. await seekToLiveHeadForLiveStream();
  979. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  980. await delayPn(60);
  981. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  982. await fixLiveAudioFn();
  983. }
  984. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  985. await seekToLiveHeadForLiveStream();
  986. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  987. await delayPn(60);
  988. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  989. await fixLiveAudioFn();
  990. }
  991. }
  992.  
  993. } catch (e) {
  994. console.log('error_F8', e)
  995. }
  996.  
  997. };
  998. let mid = 0;
  999. const getAudioElement = () => {
  1000. if (!ytdPlayerElement) {
  1001. ytdPlayerElement = [...document.querySelectorAll('ytd-player')].filter(e => !e.closest('[hidden]'))[0]
  1002. }
  1003. const audio = ytdPlayerElement ? HTMLElement.prototype.querySelector.call(ytdPlayerElement, '.video-stream.html5-main-video') : null;
  1004. return audio;
  1005. }
  1006. const _onPlayerStateChange = (k_) => {
  1007. const k = k_;
  1008. const ps = player_.getPlayerState();
  1009. if (stopAndReload) {
  1010. stopAndReload = false;
  1011. const audio = getAudioElement();
  1012. if (audio) {
  1013. prrPipeline(async () => {
  1014. await prr.then();
  1015. await stopAndReloadFn();
  1016. });
  1017. }
  1018. }
  1019. if (typeof k === 'number' && k === ps) {
  1020. const audio = getAudioElement();
  1021. if (audio) {
  1022. if (mid > 1e9) mid = 9;
  1023. const t = ++mid;
  1024. prrPipeline(async () => {
  1025. if (t !== mid) return;
  1026. await prr.then();
  1027. if (t !== mid) return;
  1028. await asyncStateChange(audio, k);
  1029. });
  1030. }
  1031. }
  1032. };
  1033.  
  1034. player_.addEventListener('onStateChange', _onPlayerStateChange);
  1035. const state0 = player_.getPlayerState();
  1036. // console.log(221, state0)
  1037. if (typeof state0 === 'number') {
  1038. _onPlayerStateChange(state0);
  1039. }
  1040.  
  1041. player_.addEventListener('onVideoProgress', () => {
  1042. updateLastActiveTimeAsync(player_);
  1043. });
  1044.  
  1045. }
  1046.  
  1047. customElements.whenDefined('ytd-player').then(() => {
  1048. const dummy = document.querySelector('ytd-player') || document.createElement('ytd-player');
  1049. const cnt = insp(dummy);
  1050. const cProto = cnt.constructor.prototype;
  1051. cProto.createMainAppPlayer932_ = cProto.createMainAppPlayer_;
  1052. cProto.initPlayer932_ = cProto.initPlayer_;
  1053. cProto.createMainAppPlayer_ = function (a, b, c) {
  1054. let r = this.createMainAppPlayer932_(a, b, c);
  1055. try {
  1056. this.mainAppPlayer_.api.then(function (e) {
  1057. setupAudioPlaying(e);
  1058. })
  1059. } finally {
  1060. return r;
  1061. }
  1062. }
  1063. cProto.initPlayer_ = function (a) {
  1064. let r = this.initPlayer932_(a);
  1065. try {
  1066. r.then(() => {
  1067. setupAudioPlaying(this.player_);
  1068. })
  1069. } finally {
  1070. return r;
  1071. }
  1072. }
  1073. })
  1074.  
  1075. let useStopAndReload = location.pathname !== '/watch';
  1076. document.addEventListener('yt-navigate-start', () => {
  1077. prr = new PromiseExternal();
  1078. if (useStopAndReload) stopAndReload = true;
  1079. });
  1080.  
  1081. document.addEventListener('yt-navigate-cache', () => {
  1082. prr = new PromiseExternal();
  1083. if (useStopAndReload) stopAndReload = true;
  1084. });
  1085.  
  1086. document.addEventListener('yt-navigate-finish', () => {
  1087. prr.resolve();
  1088. });
  1089.  
  1090. }
  1091.  
  1092. } else if (location.origin === 'https://m.youtube.com') {
  1093.  
  1094. removeBottomOverlayForMobile = async (delay) => {
  1095.  
  1096.  
  1097. let closeBtnRenderer = document.querySelector('.ytm-bottom-sheet-overlay-renderer-close.icon-close');
  1098. if (closeBtnRenderer) {
  1099.  
  1100. const btn = closeBtnRenderer.querySelector('button');
  1101. const container = closeBtnRenderer.closest('#global-loader ~ .ytm-bottom-sheet-overlay-container');
  1102.  
  1103. if (container) {
  1104. container.style.visibility = 'collapse';
  1105. container.style.zIndex = '-1';
  1106. }
  1107. if (btn) {
  1108. if (delay) {
  1109. await delayPn(delay);
  1110. }
  1111. btn.click();
  1112. }
  1113. }
  1114.  
  1115. }
  1116.  
  1117.  
  1118. let lastPlayerInfoText = '';
  1119. let mz = 0;
  1120. onVideoChangeForMobile = async () => {
  1121.  
  1122.  
  1123. let html5Container = null;
  1124.  
  1125. const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video');
  1126. if (moviePlayer) {
  1127. html5Container = moviePlayer.closest('.html5-video-container');
  1128. }
  1129. if (!html5Container) return;
  1130. let thumbnailUrl = '';
  1131.  
  1132. if (mz > 1e9) mz = 9;
  1133. let mt = ++mz;
  1134. const scriptText = await observablePromise(() => {
  1135. if (mt !== mz) return 1;
  1136. const t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]');
  1137. const tt = (t ? t.textContent : '') || '';
  1138. if (tt === lastPlayerInfoText) return;
  1139. return tt;
  1140. }).obtain();
  1141. if (typeof scriptText !== 'string') return; // 1
  1142. lastPlayerInfoText = scriptText;
  1143.  
  1144. if (!scriptText) return;
  1145.  
  1146.  
  1147. if (SHOW_VIDEO_STATIC_IMAGE) {
  1148.  
  1149. let idx1 = scriptText.indexOf('"thumbnailUrl"');
  1150. let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1;
  1151.  
  1152. if (idx1 === idx2 && idx1 > 0) {
  1153.  
  1154. let bk = 0;
  1155. let j = -1;
  1156. for (let i = idx1; i < scriptText.length; i++) {
  1157. if (i > idx1 + 20 && bk === 0) {
  1158. j = i;
  1159. break;
  1160. }
  1161. let t = scriptText.charAt(i);
  1162. if (t === '[') bk++;
  1163. else if (t === ']') bk--;
  1164. else if (t === '{') bk++;
  1165. else if (t === '}') bk--;
  1166. }
  1167.  
  1168.  
  1169. if (j > idx1) {
  1170.  
  1171. let thumbnailUrlString = scriptText.substring(idx1, j);
  1172. let thumbnailUrlObject = null;
  1173.  
  1174. try {
  1175. thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`);
  1176.  
  1177. } catch (e) { }
  1178.  
  1179. const thumbnails = thumbnailUrlObject.thumbnailUrl;
  1180.  
  1181. if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') {
  1182. if (thumbnails[0] && thumbnails[0].length > 3) {
  1183. thumbnailUrl = thumbnails[0];
  1184. }
  1185. }
  1186. }
  1187.  
  1188. }
  1189.  
  1190. // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0;
  1191.  
  1192. // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0);
  1193.  
  1194. // if (thumbnails && thumbnails.length >= 1) {
  1195. // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1196.  
  1197. // }
  1198. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  1199. html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  1200. } else {
  1201. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1202. }
  1203.  
  1204. }
  1205.  
  1206.  
  1207. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40);
  1208.  
  1209. await delayPn(80);
  1210. const audio = moviePlayer;
  1211. if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) {
  1212. await audio.click();
  1213. }
  1214.  
  1215. }
  1216.  
  1217. let player0 = null;
  1218. let mgg = null;
  1219. const mff = function (e) {
  1220. if (!player0) {
  1221. if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') {
  1222. player0 = e.target
  1223. if (mgg) mgg();
  1224. }
  1225. }
  1226.  
  1227.  
  1228. // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) {
  1229.  
  1230. // onVideoChangeForMobile();
  1231. // }
  1232.  
  1233. }
  1234.  
  1235. document.addEventListener('player-initialized', mff, true);
  1236. document.addEventListener('player-state-change', mff, true);
  1237. document.addEventListener('player-ad-state-change', mff, true);
  1238. document.addEventListener('player-detailed-error', mff, true);
  1239. document.addEventListener('player-error', mff, true);
  1240. document.addEventListener('on-play-autonav-video', mff, true);
  1241. document.addEventListener('on-play-previous-autonav-video', mff, true);
  1242. document.addEventListener('player-fullscreen-change', mff, true);
  1243. document.addEventListener('player-fullscreen-toggled', mff, true);
  1244. document.addEventListener('player-dom-paused', mff, true);
  1245. document.addEventListener('yt-show-toast', mff, true);
  1246. document.addEventListener('yt-innertube-command', mff, true);
  1247. document.addEventListener('yt-update-c3-companion', mff, true);
  1248. document.addEventListener('video-data-change', mff, true);
  1249. document.addEventListener('video-progress', mff, true);
  1250. document.addEventListener('local-media-change', mff, true);
  1251.  
  1252.  
  1253. let tc = false;
  1254. // let pw = null;
  1255. (async () => {
  1256.  
  1257. let player__;
  1258. let elm;
  1259.  
  1260. const getAudioElement = () => {
  1261. if (!elm) {
  1262. elm = player__;
  1263. }
  1264. const audio = elm ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null;
  1265. return audio;
  1266. }
  1267.  
  1268. const asyncStateChange = async (audio, k) => {
  1269. const player_ = player__;
  1270. if (!player_) return;
  1271. if (typeof player_.getPlayerState !== 'function') return;
  1272.  
  1273. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1274. // try {
  1275. // if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  1276. // } catch (e) {
  1277. // }
  1278. };
  1279. const triggerPlaying = async () => {
  1280. await player_.cancelPlayback();
  1281. await player_.pauseVideo();
  1282. await player_.playVideo();
  1283. };
  1284. const seekToLiveHeadForLiveStream = async () => {
  1285. try {
  1286. await player_.seekToLiveHead();
  1287. if ((await player_.isAtLiveHead()) === true) {
  1288. await player_.seekToStreamTime();
  1289. return true;
  1290. }
  1291. } catch (e) {
  1292. console.log('error_F9', e);
  1293. }
  1294. };
  1295. const fixLiveAudioFn = async () => {
  1296. if (audio.paused === true) {
  1297. await player_.clearVideo(); // avoid error in live streaming
  1298. await player_.clearQueue(); // avoid error in live streaming
  1299. await delayPn(300);
  1300. for (let i = 0; i < 3; i++) {
  1301. if (audio.readyState === 0) {
  1302. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1303. }
  1304. }
  1305. if (k === -1) {
  1306. await refreshAllStaleEntitiesForNonReadyAudio();
  1307. } else if (k === 3) {
  1308. while (audio.readyState === 0) {
  1309. await refreshAllStaleEntitiesForNonReadyAudio();
  1310. await triggerPlaying();
  1311. await delayPn(300);
  1312. }
  1313. // console.log(8809,audio.readyState)
  1314. }
  1315. } else if (audio.paused === false) {
  1316. if (!player_.isAtLiveHead()) {
  1317. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1318. }
  1319. while (audio.readyState === 0) {
  1320. await refreshAllStaleEntitiesForNonReadyAudio();
  1321. await triggerPlaying();
  1322. await delayPn(300);
  1323. }
  1324. if (!player_.isAtLiveHead()) {
  1325. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1326. }
  1327. await refreshAllStaleEntitiesForNonReadyAudio();
  1328. if (audio.readyState > 0 && audio.paused === true) {
  1329. await triggerPlaying();
  1330. }
  1331. }
  1332.  
  1333. }
  1334. try {
  1335.  
  1336. const ns23 = audio.networkState == 2 || audio.networkState == 3
  1337. // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted)
  1338.  
  1339.  
  1340. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300);
  1341.  
  1342. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) {
  1343. tc = true;
  1344. }
  1345. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1346. await delayPn(200);
  1347. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1348. // console.log(8806)
  1349. await fixLiveAudioFn();
  1350. }
  1351. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1352. await seekToLiveHeadForLiveStream();
  1353. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) {
  1354. await delayPn(60);
  1355. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) {
  1356. // console.log(8807)
  1357. await fixLiveAudioFn();
  1358. }
  1359.  
  1360. }
  1361.  
  1362. } catch (e) {
  1363. console.log('error_F10', e)
  1364. }
  1365.  
  1366. };
  1367. const _onPlayerStateChange = (e) => {
  1368. if (e && (e || 0).target) {
  1369. player__ = e.target
  1370. }
  1371. const player_ = player__;
  1372. try {
  1373. if (!player_) return;
  1374. let k = null;
  1375. if (e && e.detail && e.detail.state) {
  1376. k = e.detail.state
  1377. }
  1378. if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) {
  1379. const audio = getAudioElement();
  1380. if (audio) asyncStateChange(audio, k);
  1381. }
  1382. } catch (e) {
  1383. console.log('error_F11', e)
  1384. }
  1385. };
  1386.  
  1387. let idleAudioActivatePending = false;
  1388.  
  1389. const _onVideoProgress = (e) => {
  1390. if (e && (e || 0).target) {
  1391. player__ = e.target
  1392. }
  1393. const player_ = player__;
  1394. if (!player_) return;
  1395. updateLastActiveTimeAsync(player_);
  1396. if (tc) {
  1397. tc = false;
  1398. if (!idleAudioActivatePending) {
  1399. idleAudioActivatePending = true;
  1400. }
  1401. }
  1402. };
  1403.  
  1404. mgg = function () {
  1405. const player_ = player0;
  1406. if (player_) {
  1407. const state0 = player_.getPlayerState();
  1408. if (typeof state0 === 'number') {
  1409. _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } });
  1410. }
  1411. }
  1412. }
  1413.  
  1414. document.addEventListener('player-state-change', _onPlayerStateChange, true);
  1415.  
  1416. document.addEventListener('video-progress', _onVideoProgress, true);
  1417.  
  1418. })();
  1419.  
  1420. // document.addEventListener('DOMContentLoaded', (evt) => {
  1421. // const mo = new MutationObserver((mutations)=>{
  1422. // console.log(5899, mutations)
  1423. // });
  1424. // mo.observe(document, {subtree: true, childList: true})
  1425. // })
  1426.  
  1427. // window.addEventListener('onReady', (evt) => {
  1428. // console.log(6811)
  1429. // }, true);
  1430.  
  1431. // window.addEventListener('localmediachange', (evt) => {
  1432. // console.log(6812)
  1433. // }, true);
  1434.  
  1435. // window.addEventListener('onVideoDataChange', (evt) => {
  1436. // console.log(6813)
  1437. // }, true);
  1438.  
  1439. window.addEventListener('state-navigateend', async (evt) => {
  1440.  
  1441.  
  1442. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1443. ytConfigFix(config_);
  1444.  
  1445. try {
  1446. if (clickLockFn && clickTarget) {
  1447.  
  1448. let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video');
  1449. if (!a) return;
  1450.  
  1451. if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1452.  
  1453. const pr = new Promise(resolve => {
  1454.  
  1455. document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false });
  1456.  
  1457. }).then();
  1458.  
  1459. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1460. await delayPn(1);
  1461.  
  1462. if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1463. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1464. await delayPn(1);
  1465. }
  1466.  
  1467. delayRun(pr);
  1468.  
  1469. }
  1470.  
  1471. }
  1472.  
  1473. } catch (e) { console.log('error_F12', e) }
  1474.  
  1475.  
  1476. }, false);
  1477.  
  1478.  
  1479.  
  1480. // document.addEventListener('volumechange', (evt) => {
  1481. // console.log('volumechange')
  1482. // }, true)
  1483. // document.addEventListener('play', (evt) => {
  1484. // console.log('play')
  1485. // }, true)
  1486.  
  1487.  
  1488. // document.addEventListener('player-initialized', (evt) => {
  1489. // console.log(evt.type)
  1490. // }, true)
  1491. // document.addEventListener('renderer-module-load-start', (evt) => {
  1492. // console.log(evt.type)
  1493. // }, true)
  1494. // document.addEventListener('video-data-change', (evt) => {
  1495. // console.log(evt.type)
  1496. // }, true)
  1497. // document.addEventListener('player-state-change', (evt) => {
  1498. // console.log(evt.type)
  1499. // }, true)
  1500. // document.addEventListener('updateui', (evt) => {
  1501. // console.log(evt.type)
  1502. // }, true)
  1503. // document.addEventListener('renderer-module-load-end', (evt) => {
  1504. // console.log(evt.type)
  1505. // }, true)
  1506.  
  1507. // document.addEventListener('player-autonav-pause', (evt) => {
  1508. // console.log(evt.type)
  1509. // }, true)
  1510.  
  1511.  
  1512.  
  1513. // document.addEventListener('player-ad-state-change', (evt) => {
  1514. // console.log(evt.type)
  1515. // }, true)
  1516.  
  1517. // document.addEventListener('player-detailed-error', (evt) => {
  1518. // console.log(evt.type)
  1519. // }, true)
  1520.  
  1521. // document.addEventListener('player-error', (evt) => {
  1522. // console.log(evt.type)
  1523. // }, true)
  1524.  
  1525. // document.addEventListener('on-play-autonav-video', (evt) => {
  1526. // console.log(evt.type)
  1527. // }, true)
  1528.  
  1529. // document.addEventListener('on-play-previous-autonav-video', (evt) => {
  1530. // console.log(evt.type)
  1531. // }, true)
  1532.  
  1533. // document.addEventListener('player-fullscreen-change', (evt) => {
  1534. // console.log(evt.type)
  1535. // }, true)
  1536.  
  1537. // document.addEventListener('player-fullscreen-toggled', (evt) => {
  1538. // console.log(evt.type)
  1539. // }, true)
  1540.  
  1541. // document.addEventListener('player-dom-paused', (evt) => {
  1542. // console.log(evt.type)
  1543. // }, true)
  1544.  
  1545. // document.addEventListener('yt-show-toast', (evt) => {
  1546. // console.log(evt.type)
  1547. // }, true)
  1548. // document.addEventListener('yt-innertube-command', (evt) => {
  1549. // console.log(evt.type)
  1550. // }, true)
  1551. // document.addEventListener('yt-update-c3-companion', (evt) => {
  1552. // console.log(evt.type)
  1553. // }, true)
  1554. // document.addEventListener('video-progress', (evt) => {
  1555. // // console.log(evt.type)
  1556. // }, true)
  1557. // document.addEventListener('localmediachange', (evt) => {
  1558. // console.log(evt.type)
  1559. // }, true)
  1560.  
  1561.  
  1562.  
  1563. // window.addEventListener('player-initialized', (evt) => {
  1564. // console.log(evt.type)
  1565. // }, true)
  1566. // window.addEventListener('renderer-module-load-start', (evt) => {
  1567. // console.log(evt.type)
  1568. // }, true)
  1569. // window.addEventListener('video-data-change', (evt) => {
  1570. // console.log(evt.type)
  1571. // }, true)
  1572. // window.addEventListener('player-state-change', (evt) => {
  1573. // console.log(evt.type)
  1574. // }, true)
  1575. // window.addEventListener('updateui', (evt) => {
  1576. // console.log(evt.type)
  1577. // }, true)
  1578. // window.addEventListener('renderer-module-load-end', (evt) => {
  1579. // console.log(evt.type)
  1580. // }, true)
  1581.  
  1582. // window.addEventListener('player-autonav-pause', (evt) => {
  1583. // console.log(evt.type)
  1584. // }, true)
  1585.  
  1586.  
  1587.  
  1588. // window.addEventListener('player-ad-state-change', (evt) => {
  1589. // console.log(evt.type)
  1590. // }, true)
  1591.  
  1592. // window.addEventListener('player-detailed-error', (evt) => {
  1593. // console.log(evt.type)
  1594. // }, true)
  1595.  
  1596. // window.addEventListener('player-error', (evt) => {
  1597. // console.log(evt.type)
  1598. // }, true)
  1599.  
  1600. // window.addEventListener('on-play-autonav-video', (evt) => {
  1601. // console.log(evt.type)
  1602. // }, true)
  1603.  
  1604. // window.addEventListener('on-play-previous-autonav-video', (evt) => {
  1605. // console.log(evt.type)
  1606. // }, true)
  1607.  
  1608. // window.addEventListener('player-fullscreen-change', (evt) => {
  1609. // console.log(evt.type)
  1610. // }, true)
  1611.  
  1612. // window.addEventListener('player-fullscreen-toggled', (evt) => {
  1613. // console.log(evt.type)
  1614. // }, true)
  1615.  
  1616. // window.addEventListener('player-dom-paused', (evt) => {
  1617. // console.log(evt.type)
  1618. // }, true)
  1619.  
  1620. // window.addEventListener('yt-show-toast', (evt) => {
  1621. // console.log(evt.type)
  1622. // }, true)
  1623. // window.addEventListener('yt-innertube-command', (evt) => {
  1624. // console.log(evt.type)
  1625. // }, true)
  1626. // window.addEventListener('yt-update-c3-companion', (evt) => {
  1627. // console.log(evt.type)
  1628. // }, true)
  1629. // window.addEventListener('video-progress', (evt) => {
  1630. // // console.log(evt.type)
  1631. // }, true)
  1632. // window.addEventListener('localmediachange', (evt) => {
  1633. // console.log(evt.type)
  1634. // }, true)
  1635.  
  1636.  
  1637.  
  1638. // document.addEventListener('player-error', (evt) => {
  1639. // console.log(3001, evt.type, evt)
  1640. // }, true)
  1641. // document.addEventListener('player-detailed-error', (evt) => {
  1642. // console.log(3002, evt.type, evt)
  1643. // }, true)
  1644.  
  1645.  
  1646.  
  1647. async function delayRun(pr) {
  1648.  
  1649. let q = document.querySelector('#movie_player');
  1650. if (!q) return;
  1651. let a = document.querySelector('.video-stream.html5-main-video');
  1652. if (!a) return;
  1653.  
  1654. await pr.then();
  1655.  
  1656. if (fa !== 1) {
  1657. return;
  1658. } else if (a.muted === true) {
  1659. return;
  1660. } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1661. if (a.paused === false) return;
  1662. } else {
  1663. return;
  1664. }
  1665.  
  1666. if (document.querySelector('.player-controls-content')) return;
  1667.  
  1668. if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1669.  
  1670. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1671.  
  1672. }
  1673.  
  1674. if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) {
  1675.  
  1676. if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead();
  1677. if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) {
  1678. if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime();
  1679. }
  1680. }
  1681.  
  1682. }
  1683.  
  1684. durationchangeForMobile = true;
  1685.  
  1686. }
  1687.  
  1688. attachOneTimeEvent('yt-action', function () {
  1689. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1690. ytConfigFix(config_);
  1691. });
  1692.  
  1693. let prepared = false;
  1694. function prepare() {
  1695. if (prepared) return;
  1696. prepared = true;
  1697.  
  1698. if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') {
  1699.  
  1700. for (const [k, v] of Object.entries(_yt_player)) {
  1701.  
  1702. if (typeof v === 'function' && typeof v.prototype.clone === 'function'
  1703. && typeof v.prototype.get === 'function' && typeof v.prototype.set === 'function'
  1704.  
  1705. && typeof v.prototype.isEmpty === 'undefined' && typeof v.prototype.forEach === 'undefined'
  1706. && typeof v.prototype.clear === 'undefined'
  1707.  
  1708. ) {
  1709.  
  1710. key = k;
  1711.  
  1712. }
  1713.  
  1714. }
  1715.  
  1716. }
  1717.  
  1718. if (key) {
  1719.  
  1720. const ClassX = _yt_player[key];
  1721. _yt_player[key] = class extends ClassX {
  1722. constructor(...args) {
  1723.  
  1724. if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = '';
  1725. super(...args);
  1726.  
  1727. }
  1728. }
  1729. _yt_player[key].luX1Y = 1;
  1730. }
  1731.  
  1732. }
  1733. let s3 = Symbol();
  1734.  
  1735. generalRegister('deviceIsAudioOnly', s3, (p) => {
  1736. return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p)
  1737. }, {
  1738.  
  1739. get() {
  1740. return this[s3];
  1741. },
  1742. set(nv) {
  1743. if (typeof nv === 'boolean') this[s3] = true;
  1744. else this[s3] = undefined;
  1745. prepare();
  1746. return true;
  1747. },
  1748. enumerable: false,
  1749. configurable: true
  1750.  
  1751. });
  1752.  
  1753.  
  1754. let s1 = Symbol();
  1755. let s2 = Symbol();
  1756. Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', {
  1757. get() {
  1758. // console.log(501, this.constructor.prototype)
  1759. return undefined;
  1760. },
  1761. set(nv) {
  1762. return true;
  1763. },
  1764. enumerable: false,
  1765. configurable: true
  1766. });
  1767.  
  1768. Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', {
  1769. get() {
  1770. // console.log(502, this.constructor.prototype)
  1771. return this[s1];
  1772. },
  1773. set(nv) {
  1774. if (typeof nv === 'boolean') this[s1] = false;
  1775. else this[s1] = undefined;
  1776. return true;
  1777. },
  1778. enumerable: false,
  1779. configurable: true
  1780. });
  1781.  
  1782. Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', {
  1783. get() {
  1784. // console.log(503, this.constructor.prototype)
  1785. return this[s2];
  1786. },
  1787. set(nv) {
  1788. if (typeof nv === 'boolean') this[s2] = false;
  1789. else this[s2] = undefined;
  1790. return true;
  1791. },
  1792. enumerable: false,
  1793. configurable: true
  1794. });
  1795.  
  1796.  
  1797. const supportedFormatsConfig = () => {
  1798.  
  1799. function typeTest(type) {
  1800. if (typeof type === 'string' && type.startsWith('video/')) {
  1801. return false;
  1802. }
  1803. }
  1804.  
  1805. // return a custom MIME type checker that can defer to the original function
  1806. function makeModifiedTypeChecker(origChecker) {
  1807. // Check if a video type is allowed
  1808. return function (type) {
  1809. let res = undefined;
  1810. if (type === undefined) res = false;
  1811. else {
  1812. res = typeTest.call(this, type);
  1813. }
  1814. if (res === undefined) res = origChecker.apply(this, arguments);
  1815. return res;
  1816. };
  1817. }
  1818.  
  1819. // Override video element canPlayType() function
  1820. const proto = (HTMLVideoElement || 0).prototype;
  1821. if (proto && typeof proto.canPlayType == 'function') {
  1822. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  1823. }
  1824.  
  1825. // Override media source extension isTypeSupported() function
  1826. const mse = window.MediaSource;
  1827. // Check for MSE support before use
  1828. if (mse && typeof mse.isTypeSupported == 'function') {
  1829. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  1830. }
  1831.  
  1832. };
  1833.  
  1834. supportedFormatsConfig();
  1835. }
  1836.  
  1837. const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? (await GM.getValue("isEnable_aWsjF", true)) : null;
  1838. if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
  1839. if (isEnable) {
  1840. const element = document.createElement('button');
  1841. element.setAttribute('onclick', `(${pageInjectionCode})()`);
  1842. element.click();
  1843. }
  1844.  
  1845. GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
  1846. await GM.setValue("isEnable_aWsjF", !isEnable);
  1847. document.documentElement.setAttribute('forceRefresh032', '');
  1848. location.reload();
  1849. });
  1850.  
  1851. let messageCount = 0;
  1852. let busy = false;
  1853. window.addEventListener('message', (evt) => {
  1854.  
  1855. const v = ((evt || 0).data || 0).ZECxh;
  1856. if (typeof v === 'boolean') {
  1857. if (messageCount > 1e9) messageCount = 9;
  1858. const t = ++messageCount;
  1859. if (v && isEnable) {
  1860. requestAnimationFrame(async () => {
  1861. if (t !== messageCount) return;
  1862. if (busy) return;
  1863. busy = true;
  1864. if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
  1865. await GM.setValue("isEnable_aWsjF", !isEnable);
  1866. document.documentElement.setAttribute('forceRefresh032', '');
  1867. location.reload();
  1868. }
  1869. busy = false;
  1870. });
  1871. }
  1872. }
  1873.  
  1874. });
  1875.  
  1876.  
  1877. const pLoad = new Promise(resolve => {
  1878. if (document.readyState !== 'loading') {
  1879. resolve();
  1880. } else {
  1881. window.addEventListener("DOMContentLoaded", resolve, false);
  1882. }
  1883. });
  1884.  
  1885.  
  1886. function contextmenuInfoItemAppearedFn(target) {
  1887.  
  1888. const btn = target.closest('.ytp-menuitem[role="menuitem"]');
  1889. if (!btn) return;
  1890. if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return;
  1891. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1892. const newBtn = btn.cloneNode(true)
  1893. newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1894. newBtn.classList.add('audio-only-toggle-btn');
  1895. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1896. newBtn.addEventListener('click', async () => {
  1897. await GM.setValue("isEnable_aWsjF", !isEnable);
  1898. document.documentElement.setAttribute('forceRefresh032', '');
  1899. location.reload();
  1900. });
  1901. let t;
  1902. let h = 0;
  1903. t = btn.closest('.ytp-panel-menu[style*="height"]');
  1904. if (t) t.style.height = t.scrollHeight + 'px';
  1905. t = btn.closest('.ytp-panel[style*="height"]');
  1906. if (t) t.style.height = (h = t.scrollHeight) + 'px';
  1907. t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]');
  1908. if (t && h > 0) t.style.height = h + 'px';
  1909. }
  1910.  
  1911.  
  1912. function mobileMenuItemAppearedFn(target) {
  1913.  
  1914. const btn = target.closest('ytm-menu-item');
  1915. if (!btn) return;
  1916. if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return;
  1917. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1918. const newBtn = btn.cloneNode(true);
  1919. newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1920. newBtn.classList.add('audio-only-toggle-btn');
  1921. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1922. newBtn.addEventListener('click', async () => {
  1923. await GM.setValue("isEnable_aWsjF", !isEnable);
  1924. document.documentElement.setAttribute('forceRefresh032', '');
  1925. location.reload();
  1926. });
  1927. }
  1928.  
  1929.  
  1930. pLoad.then(() => {
  1931.  
  1932. document.addEventListener('animationstart', (evt) => {
  1933. const animationName = evt.animationName;
  1934. if (!animationName) return;
  1935.  
  1936. if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target);
  1937. if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target);
  1938.  
  1939. }, true);
  1940.  
  1941. const cssForEnabled = isEnable ? `
  1942.  
  1943. .html5-video-player {
  1944. background-color: black;
  1945. }
  1946.  
  1947. [style*="--audio-only-thumbnail-image"]{
  1948. background-image: var(--audio-only-thumbnail-image);
  1949. object-fit: contain;
  1950. background-position: center;
  1951. background-size: contain;
  1952. background-repeat: no-repeat;
  1953. }
  1954. .html5-video-player.ended-mode [style*="--audio-only-thumbnail-image"]{
  1955. background-image: none;
  1956. }
  1957.  
  1958. .html5-video-player.ytp-ce-shown .html5-video-container {
  1959. opacity: 0.5;
  1960. transition: opacity 0.5s;
  1961. }
  1962.  
  1963. ytd-video-preview #media-container div#player-container,
  1964. ytd-video-preview #media-container div#thumbnail-container{
  1965. transition: initial !important;
  1966. transition-duration:0ms !important;
  1967. transition-delay:0ms !important;
  1968. }
  1969. ytd-video-preview #media-container div#thumbnail-container{
  1970. /* pointer-events:none !important; */
  1971. opacity:0;
  1972. /* z-index:-1; */
  1973. }
  1974. ytd-video-preview #media-container div#player-container,
  1975. ytd-video-preview #media-container div#inline-preview-player{
  1976. background-color:transparent !important;
  1977. background-image:none !important;
  1978. }
  1979.  
  1980. #movie_player > .html5-video-container:not(:empty) {
  1981. box-sizing: border-box;
  1982. height: 100%;
  1983. }
  1984.  
  1985. `: "";
  1986.  
  1987. const style = document.createElement('style');
  1988. style.id = 'fm9v0';
  1989. style.textContent = `
  1990.  
  1991. ${cssForEnabled}
  1992.  
  1993. @keyframes mobileMenuItemAppeared {
  1994. 0% {
  1995. background-position-x: 3px;
  1996. }
  1997. 100% {
  1998. background-position-x: 4px;
  1999. }
  2000. }
  2001. ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type {
  2002. animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards;
  2003. }
  2004. @keyframes contextmenuInfoItemAppeared {
  2005. 0% {
  2006. background-position-x: 3px;
  2007. }
  2008. 100% {
  2009. background-position-x: 4px;
  2010. }
  2011. }
  2012. .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{
  2013. animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards;
  2014. }
  2015. #confirmDialog794 {
  2016. z-index:999999 !important;
  2017. display: none;
  2018. /* Hidden by default */
  2019. position: fixed;
  2020. /* Stay in place */
  2021. z-index: 1;
  2022. /* Sit on top */
  2023. left: 0;
  2024. top: 0;
  2025. width: 100%;
  2026. /* Full width */
  2027. height: 100%;
  2028. /* Full height */
  2029. overflow: auto;
  2030. /* Enable scroll if needed */
  2031. background-color: rgba(0,0,0,0.4);
  2032. /* Black w/ opacity */
  2033. }
  2034. #confirmDialog794 .confirm-box {
  2035. position:relative;
  2036. color: black;
  2037. z-index:999999 !important;
  2038. background-color: #fefefe;
  2039. margin: 15% auto;
  2040. /* 15% from the top and centered */
  2041. padding: 20px;
  2042. border: 1px solid #888;
  2043. width: 30%;
  2044. /* Could be more or less, depending on screen size */
  2045. box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  2046. }
  2047. #confirmDialog794 .confirm-buttons {
  2048. text-align: right;
  2049. }
  2050. #confirmDialog794 button {
  2051. margin-left: 10px;
  2052. }
  2053. `
  2054. document.head.appendChild(style);
  2055.  
  2056. if (false && isEnable) {
  2057. let mzId = 0;
  2058.  
  2059. let mz = 0;
  2060. const mof = async () => {
  2061. mzId && clearInterval(mzId);
  2062. if (mz > 1e9) mz = 9;
  2063. const mt = ++mz;
  2064.  
  2065. let q = document.querySelector('#video-preview > ytd-video-preview.style-scope.ytd-app');
  2066. if(!q) return;
  2067. if (q.hasAttribute('active') && !q.hasAttribute('hidden')) {
  2068.  
  2069. }else{
  2070. return;
  2071. }
  2072.  
  2073.  
  2074. let inlinePreviewPlayer = null;
  2075. const ss = [HTMLElement.prototype.querySelector.call(q, '#inline-preview-player')].filter(e=>e && !e.closest('[hidden]'));
  2076. if (ss && ss.length === 1) {
  2077. inlinePreviewPlayer = ss[0];
  2078. }
  2079. if(!inlinePreviewPlayer) return;
  2080.  
  2081. const f = ()=>{
  2082. if (mz !== mt || !(q.hasAttribute('active') && !q.hasAttribute('hidden')) || !(inlinePreviewPlayer && inlinePreviewPlayer.isConnected === true)) {
  2083. mzId && clearInterval(mzId);
  2084. mzId= 0;
  2085. return;
  2086. }
  2087.  
  2088. const s = inlinePreviewPlayer;
  2089. s.classList.remove('ytp-hide-inline-preview-progress-bar');
  2090. s.classList.remove('ytp-hide-inline-preview-audio-controls');
  2091. s.classList.add('ytp-show-inline-preview-progress-bar');
  2092. s.classList.add('ytp-show-inline-preview-audio-controls');
  2093. s.classList.remove('ytp-autohide');
  2094. if (q.hasAttribute('hide-volume-controls')) {
  2095. q.removeAttribute('hide-volume-controls')
  2096. }
  2097. if(s.classList.contains('playing-mode') && !q.hasAttribute('playing')){
  2098. q.setAttribute('playing','')
  2099. }
  2100. }
  2101. mzId = setInterval(f, 40);
  2102. f();
  2103.  
  2104. }
  2105. const mo = new MutationObserver(mof);
  2106. document.addEventListener('yt-navigate-finish', async function () {
  2107.  
  2108. for (const s of document.querySelectorAll('ytd-video-preview')) {
  2109. mo.observe(s, {
  2110. attributes: true,
  2111. attributeFilter: ["hidden", "active"],
  2112. attributeOldValue: false
  2113. });
  2114. mof();
  2115. }
  2116.  
  2117. }, false);
  2118. }
  2119. })
  2120.  
  2121.  
  2122. })();