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.7
  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' && entry.serializedExperimentFlags.length > 16) {
  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. const configFixBeforeCreate = () => {
  1054. try {
  1055. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1056. if (config_) {
  1057. ytConfigFix(config_);
  1058. }
  1059. } catch (e) { }
  1060. }
  1061. cProto.createMainAppPlayer_ = function (a, b, c) {
  1062. configFixBeforeCreate();
  1063. let r = this.createMainAppPlayer932_(a, b, c);
  1064. try {
  1065. this.mainAppPlayer_.api.then(function (e) {
  1066. setupAudioPlaying(e);
  1067. })
  1068. } finally {
  1069. return r;
  1070. }
  1071. }
  1072. cProto.initPlayer_ = function (a) {
  1073. configFixBeforeCreate();
  1074. let r = this.initPlayer932_(a);
  1075. try {
  1076. r.then(() => {
  1077. setupAudioPlaying(this.player_);
  1078. })
  1079. } finally {
  1080. return r;
  1081. }
  1082. }
  1083. })
  1084.  
  1085. let useStopAndReload = location.pathname !== '/watch';
  1086. document.addEventListener('yt-navigate-start', () => {
  1087. prr = new PromiseExternal();
  1088. if (useStopAndReload) stopAndReload = true;
  1089. });
  1090.  
  1091. document.addEventListener('yt-navigate-cache', () => {
  1092. prr = new PromiseExternal();
  1093. if (useStopAndReload) stopAndReload = true;
  1094. });
  1095.  
  1096. document.addEventListener('yt-navigate-finish', () => {
  1097. prr.resolve();
  1098. });
  1099.  
  1100. }
  1101.  
  1102. } else if (location.origin === 'https://m.youtube.com') {
  1103.  
  1104. removeBottomOverlayForMobile = async (delay) => {
  1105.  
  1106.  
  1107. let closeBtnRenderer = document.querySelector('.ytm-bottom-sheet-overlay-renderer-close.icon-close');
  1108. if (closeBtnRenderer) {
  1109.  
  1110. const btn = closeBtnRenderer.querySelector('button');
  1111. const container = closeBtnRenderer.closest('#global-loader ~ .ytm-bottom-sheet-overlay-container');
  1112.  
  1113. if (container) {
  1114. container.style.visibility = 'collapse';
  1115. container.style.zIndex = '-1';
  1116. }
  1117. if (btn) {
  1118. if (delay) {
  1119. await delayPn(delay);
  1120. }
  1121. btn.click();
  1122. }
  1123. }
  1124.  
  1125. }
  1126.  
  1127.  
  1128. let lastPlayerInfoText = '';
  1129. let mz = 0;
  1130. onVideoChangeForMobile = async () => {
  1131.  
  1132.  
  1133. let html5Container = null;
  1134.  
  1135. const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video');
  1136. if (moviePlayer) {
  1137. html5Container = moviePlayer.closest('.html5-video-container');
  1138. }
  1139. if (!html5Container) return;
  1140. let thumbnailUrl = '';
  1141.  
  1142. if (mz > 1e9) mz = 9;
  1143. let mt = ++mz;
  1144. const scriptText = await observablePromise(() => {
  1145. if (mt !== mz) return 1;
  1146. const t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]');
  1147. const tt = (t ? t.textContent : '') || '';
  1148. if (tt === lastPlayerInfoText) return;
  1149. return tt;
  1150. }).obtain();
  1151. if (typeof scriptText !== 'string') return; // 1
  1152. lastPlayerInfoText = scriptText;
  1153.  
  1154. if (!scriptText) return;
  1155.  
  1156.  
  1157. if (SHOW_VIDEO_STATIC_IMAGE) {
  1158.  
  1159. let idx1 = scriptText.indexOf('"thumbnailUrl"');
  1160. let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1;
  1161.  
  1162. if (idx1 === idx2 && idx1 > 0) {
  1163.  
  1164. let bk = 0;
  1165. let j = -1;
  1166. for (let i = idx1; i < scriptText.length; i++) {
  1167. if (i > idx1 + 20 && bk === 0) {
  1168. j = i;
  1169. break;
  1170. }
  1171. let t = scriptText.charAt(i);
  1172. if (t === '[') bk++;
  1173. else if (t === ']') bk--;
  1174. else if (t === '{') bk++;
  1175. else if (t === '}') bk--;
  1176. }
  1177.  
  1178.  
  1179. if (j > idx1) {
  1180.  
  1181. let thumbnailUrlString = scriptText.substring(idx1, j);
  1182. let thumbnailUrlObject = null;
  1183.  
  1184. try {
  1185. thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`);
  1186.  
  1187. } catch (e) { }
  1188.  
  1189. const thumbnails = thumbnailUrlObject.thumbnailUrl;
  1190.  
  1191. if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') {
  1192. if (thumbnails[0] && thumbnails[0].length > 3) {
  1193. thumbnailUrl = thumbnails[0];
  1194. }
  1195. }
  1196. }
  1197.  
  1198. }
  1199.  
  1200. // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0;
  1201.  
  1202. // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0);
  1203.  
  1204. // if (thumbnails && thumbnails.length >= 1) {
  1205. // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1206.  
  1207. // }
  1208. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  1209. html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  1210. } else {
  1211. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1212. }
  1213.  
  1214. }
  1215.  
  1216.  
  1217. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40);
  1218.  
  1219. await delayPn(80);
  1220. const audio = moviePlayer;
  1221. if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) {
  1222. await audio.click();
  1223. }
  1224.  
  1225. }
  1226.  
  1227. let player0 = null;
  1228. let mgg = null;
  1229. const mff = function (e) {
  1230. if (!player0) {
  1231. if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') {
  1232. player0 = e.target
  1233. if (mgg) mgg();
  1234. }
  1235. }
  1236.  
  1237.  
  1238. // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) {
  1239.  
  1240. // onVideoChangeForMobile();
  1241. // }
  1242.  
  1243. }
  1244.  
  1245. document.addEventListener('player-initialized', mff, true);
  1246. document.addEventListener('player-state-change', mff, true);
  1247. document.addEventListener('player-ad-state-change', mff, true);
  1248. document.addEventListener('player-detailed-error', mff, true);
  1249. document.addEventListener('player-error', mff, true);
  1250. document.addEventListener('on-play-autonav-video', mff, true);
  1251. document.addEventListener('on-play-previous-autonav-video', mff, true);
  1252. document.addEventListener('player-fullscreen-change', mff, true);
  1253. document.addEventListener('player-fullscreen-toggled', mff, true);
  1254. document.addEventListener('player-dom-paused', mff, true);
  1255. document.addEventListener('yt-show-toast', mff, true);
  1256. document.addEventListener('yt-innertube-command', mff, true);
  1257. document.addEventListener('yt-update-c3-companion', mff, true);
  1258. document.addEventListener('video-data-change', mff, true);
  1259. document.addEventListener('video-progress', mff, true);
  1260. document.addEventListener('local-media-change', mff, true);
  1261.  
  1262.  
  1263. let tc = false;
  1264. // let pw = null;
  1265. (async () => {
  1266.  
  1267. let player__;
  1268. let elm;
  1269.  
  1270. const getAudioElement = () => {
  1271. if (!elm) {
  1272. elm = player__;
  1273. }
  1274. const audio = elm ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null;
  1275. return audio;
  1276. }
  1277.  
  1278. const asyncStateChange = async (audio, k) => {
  1279. const player_ = player__;
  1280. if (!player_) return;
  1281. if (typeof player_.getPlayerState !== 'function') return;
  1282.  
  1283. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1284. // try {
  1285. // if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  1286. // } catch (e) {
  1287. // }
  1288. };
  1289. const triggerPlaying = async () => {
  1290. await player_.cancelPlayback();
  1291. await player_.pauseVideo();
  1292. await player_.playVideo();
  1293. };
  1294. const seekToLiveHeadForLiveStream = async () => {
  1295. try {
  1296. await player_.seekToLiveHead();
  1297. if ((await player_.isAtLiveHead()) === true) {
  1298. await player_.seekToStreamTime();
  1299. return true;
  1300. }
  1301. } catch (e) {
  1302. console.log('error_F9', e);
  1303. }
  1304. };
  1305. const fixLiveAudioFn = async () => {
  1306. if (audio.paused === true) {
  1307. await player_.clearVideo(); // avoid error in live streaming
  1308. await player_.clearQueue(); // avoid error in live streaming
  1309. await delayPn(300);
  1310. for (let i = 0; i < 3; i++) {
  1311. if (audio.readyState === 0) {
  1312. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1313. }
  1314. }
  1315. if (k === -1) {
  1316. await refreshAllStaleEntitiesForNonReadyAudio();
  1317. } else if (k === 3) {
  1318. while (audio.readyState === 0) {
  1319. await refreshAllStaleEntitiesForNonReadyAudio();
  1320. await triggerPlaying();
  1321. await delayPn(300);
  1322. }
  1323. // console.log(8809,audio.readyState)
  1324. }
  1325. } else if (audio.paused === false) {
  1326. if (!player_.isAtLiveHead()) {
  1327. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1328. }
  1329. while (audio.readyState === 0) {
  1330. await refreshAllStaleEntitiesForNonReadyAudio();
  1331. await triggerPlaying();
  1332. await delayPn(300);
  1333. }
  1334. if (!player_.isAtLiveHead()) {
  1335. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1336. }
  1337. await refreshAllStaleEntitiesForNonReadyAudio();
  1338. if (audio.readyState > 0 && audio.paused === true) {
  1339. await triggerPlaying();
  1340. }
  1341. }
  1342.  
  1343. }
  1344. try {
  1345.  
  1346. const ns23 = audio.networkState == 2 || audio.networkState == 3
  1347. // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted)
  1348.  
  1349.  
  1350. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300);
  1351.  
  1352. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) {
  1353. tc = true;
  1354. }
  1355. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1356. await delayPn(200);
  1357. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1358. // console.log(8806)
  1359. await fixLiveAudioFn();
  1360. }
  1361. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1362. await seekToLiveHeadForLiveStream();
  1363. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) {
  1364. await delayPn(60);
  1365. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) {
  1366. // console.log(8807)
  1367. await fixLiveAudioFn();
  1368. }
  1369.  
  1370. }
  1371.  
  1372. } catch (e) {
  1373. console.log('error_F10', e)
  1374. }
  1375.  
  1376. };
  1377. const _onPlayerStateChange = (e) => {
  1378. if (e && (e || 0).target) {
  1379. player__ = e.target
  1380. }
  1381. const player_ = player__;
  1382. try {
  1383. if (!player_) return;
  1384. let k = null;
  1385. if (e && e.detail && e.detail.state) {
  1386. k = e.detail.state
  1387. }
  1388. if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) {
  1389. const audio = getAudioElement();
  1390. if (audio) asyncStateChange(audio, k);
  1391. }
  1392. } catch (e) {
  1393. console.log('error_F11', e)
  1394. }
  1395. };
  1396.  
  1397. let idleAudioActivatePending = false;
  1398.  
  1399. const _onVideoProgress = (e) => {
  1400. if (e && (e || 0).target) {
  1401. player__ = e.target
  1402. }
  1403. const player_ = player__;
  1404. if (!player_) return;
  1405. updateLastActiveTimeAsync(player_);
  1406. if (tc) {
  1407. tc = false;
  1408. if (!idleAudioActivatePending) {
  1409. idleAudioActivatePending = true;
  1410. }
  1411. }
  1412. };
  1413.  
  1414. mgg = function () {
  1415. const player_ = player0;
  1416. if (player_) {
  1417. const state0 = player_.getPlayerState();
  1418. if (typeof state0 === 'number') {
  1419. _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } });
  1420. }
  1421. }
  1422. }
  1423.  
  1424. document.addEventListener('player-state-change', _onPlayerStateChange, true);
  1425.  
  1426. document.addEventListener('video-progress', _onVideoProgress, true);
  1427.  
  1428. })();
  1429.  
  1430. // document.addEventListener('DOMContentLoaded', (evt) => {
  1431. // const mo = new MutationObserver((mutations)=>{
  1432. // console.log(5899, mutations)
  1433. // });
  1434. // mo.observe(document, {subtree: true, childList: true})
  1435. // })
  1436.  
  1437. // window.addEventListener('onReady', (evt) => {
  1438. // console.log(6811)
  1439. // }, true);
  1440.  
  1441. // window.addEventListener('localmediachange', (evt) => {
  1442. // console.log(6812)
  1443. // }, true);
  1444.  
  1445. // window.addEventListener('onVideoDataChange', (evt) => {
  1446. // console.log(6813)
  1447. // }, true);
  1448.  
  1449. window.addEventListener('state-navigateend', async (evt) => {
  1450.  
  1451.  
  1452. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1453. ytConfigFix(config_);
  1454.  
  1455. try {
  1456. if (clickLockFn && clickTarget) {
  1457.  
  1458. let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video');
  1459. if (!a) return;
  1460.  
  1461. if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1462.  
  1463. const pr = new Promise(resolve => {
  1464.  
  1465. document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false });
  1466.  
  1467. }).then();
  1468.  
  1469. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1470. await delayPn(1);
  1471.  
  1472. if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1473. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1474. await delayPn(1);
  1475. }
  1476.  
  1477. delayRun(pr);
  1478.  
  1479. }
  1480.  
  1481. }
  1482.  
  1483. } catch (e) { console.log('error_F12', e) }
  1484.  
  1485.  
  1486. }, false);
  1487.  
  1488.  
  1489.  
  1490. // document.addEventListener('volumechange', (evt) => {
  1491. // console.log('volumechange')
  1492. // }, true)
  1493. // document.addEventListener('play', (evt) => {
  1494. // console.log('play')
  1495. // }, true)
  1496.  
  1497.  
  1498. // document.addEventListener('player-initialized', (evt) => {
  1499. // console.log(evt.type)
  1500. // }, true)
  1501. // document.addEventListener('renderer-module-load-start', (evt) => {
  1502. // console.log(evt.type)
  1503. // }, true)
  1504. // document.addEventListener('video-data-change', (evt) => {
  1505. // console.log(evt.type)
  1506. // }, true)
  1507. // document.addEventListener('player-state-change', (evt) => {
  1508. // console.log(evt.type)
  1509. // }, true)
  1510. // document.addEventListener('updateui', (evt) => {
  1511. // console.log(evt.type)
  1512. // }, true)
  1513. // document.addEventListener('renderer-module-load-end', (evt) => {
  1514. // console.log(evt.type)
  1515. // }, true)
  1516.  
  1517. // document.addEventListener('player-autonav-pause', (evt) => {
  1518. // console.log(evt.type)
  1519. // }, true)
  1520.  
  1521.  
  1522.  
  1523. // document.addEventListener('player-ad-state-change', (evt) => {
  1524. // console.log(evt.type)
  1525. // }, true)
  1526.  
  1527. // document.addEventListener('player-detailed-error', (evt) => {
  1528. // console.log(evt.type)
  1529. // }, true)
  1530.  
  1531. // document.addEventListener('player-error', (evt) => {
  1532. // console.log(evt.type)
  1533. // }, true)
  1534.  
  1535. // document.addEventListener('on-play-autonav-video', (evt) => {
  1536. // console.log(evt.type)
  1537. // }, true)
  1538.  
  1539. // document.addEventListener('on-play-previous-autonav-video', (evt) => {
  1540. // console.log(evt.type)
  1541. // }, true)
  1542.  
  1543. // document.addEventListener('player-fullscreen-change', (evt) => {
  1544. // console.log(evt.type)
  1545. // }, true)
  1546.  
  1547. // document.addEventListener('player-fullscreen-toggled', (evt) => {
  1548. // console.log(evt.type)
  1549. // }, true)
  1550.  
  1551. // document.addEventListener('player-dom-paused', (evt) => {
  1552. // console.log(evt.type)
  1553. // }, true)
  1554.  
  1555. // document.addEventListener('yt-show-toast', (evt) => {
  1556. // console.log(evt.type)
  1557. // }, true)
  1558. // document.addEventListener('yt-innertube-command', (evt) => {
  1559. // console.log(evt.type)
  1560. // }, true)
  1561. // document.addEventListener('yt-update-c3-companion', (evt) => {
  1562. // console.log(evt.type)
  1563. // }, true)
  1564. // document.addEventListener('video-progress', (evt) => {
  1565. // // console.log(evt.type)
  1566. // }, true)
  1567. // document.addEventListener('localmediachange', (evt) => {
  1568. // console.log(evt.type)
  1569. // }, true)
  1570.  
  1571.  
  1572.  
  1573. // window.addEventListener('player-initialized', (evt) => {
  1574. // console.log(evt.type)
  1575. // }, true)
  1576. // window.addEventListener('renderer-module-load-start', (evt) => {
  1577. // console.log(evt.type)
  1578. // }, true)
  1579. // window.addEventListener('video-data-change', (evt) => {
  1580. // console.log(evt.type)
  1581. // }, true)
  1582. // window.addEventListener('player-state-change', (evt) => {
  1583. // console.log(evt.type)
  1584. // }, true)
  1585. // window.addEventListener('updateui', (evt) => {
  1586. // console.log(evt.type)
  1587. // }, true)
  1588. // window.addEventListener('renderer-module-load-end', (evt) => {
  1589. // console.log(evt.type)
  1590. // }, true)
  1591.  
  1592. // window.addEventListener('player-autonav-pause', (evt) => {
  1593. // console.log(evt.type)
  1594. // }, true)
  1595.  
  1596.  
  1597.  
  1598. // window.addEventListener('player-ad-state-change', (evt) => {
  1599. // console.log(evt.type)
  1600. // }, true)
  1601.  
  1602. // window.addEventListener('player-detailed-error', (evt) => {
  1603. // console.log(evt.type)
  1604. // }, true)
  1605.  
  1606. // window.addEventListener('player-error', (evt) => {
  1607. // console.log(evt.type)
  1608. // }, true)
  1609.  
  1610. // window.addEventListener('on-play-autonav-video', (evt) => {
  1611. // console.log(evt.type)
  1612. // }, true)
  1613.  
  1614. // window.addEventListener('on-play-previous-autonav-video', (evt) => {
  1615. // console.log(evt.type)
  1616. // }, true)
  1617.  
  1618. // window.addEventListener('player-fullscreen-change', (evt) => {
  1619. // console.log(evt.type)
  1620. // }, true)
  1621.  
  1622. // window.addEventListener('player-fullscreen-toggled', (evt) => {
  1623. // console.log(evt.type)
  1624. // }, true)
  1625.  
  1626. // window.addEventListener('player-dom-paused', (evt) => {
  1627. // console.log(evt.type)
  1628. // }, true)
  1629.  
  1630. // window.addEventListener('yt-show-toast', (evt) => {
  1631. // console.log(evt.type)
  1632. // }, true)
  1633. // window.addEventListener('yt-innertube-command', (evt) => {
  1634. // console.log(evt.type)
  1635. // }, true)
  1636. // window.addEventListener('yt-update-c3-companion', (evt) => {
  1637. // console.log(evt.type)
  1638. // }, true)
  1639. // window.addEventListener('video-progress', (evt) => {
  1640. // // console.log(evt.type)
  1641. // }, true)
  1642. // window.addEventListener('localmediachange', (evt) => {
  1643. // console.log(evt.type)
  1644. // }, true)
  1645.  
  1646.  
  1647.  
  1648. // document.addEventListener('player-error', (evt) => {
  1649. // console.log(3001, evt.type, evt)
  1650. // }, true)
  1651. // document.addEventListener('player-detailed-error', (evt) => {
  1652. // console.log(3002, evt.type, evt)
  1653. // }, true)
  1654.  
  1655.  
  1656.  
  1657. async function delayRun(pr) {
  1658.  
  1659. let q = document.querySelector('#movie_player');
  1660. if (!q) return;
  1661. let a = document.querySelector('.video-stream.html5-main-video');
  1662. if (!a) return;
  1663.  
  1664. await pr.then();
  1665.  
  1666. if (fa !== 1) {
  1667. return;
  1668. } else if (a.muted === true) {
  1669. return;
  1670. } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1671. if (a.paused === false) return;
  1672. } else {
  1673. return;
  1674. }
  1675.  
  1676. if (document.querySelector('.player-controls-content')) return;
  1677.  
  1678. if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1679.  
  1680. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1681.  
  1682. }
  1683.  
  1684. if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) {
  1685.  
  1686. if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead();
  1687. if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) {
  1688. if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime();
  1689. }
  1690. }
  1691.  
  1692. }
  1693.  
  1694. durationchangeForMobile = true;
  1695.  
  1696. }
  1697.  
  1698. attachOneTimeEvent('yt-action', function () {
  1699. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1700. ytConfigFix(config_);
  1701. });
  1702.  
  1703. let prepared = false;
  1704. function prepare() {
  1705. if (prepared) return;
  1706. prepared = true;
  1707.  
  1708. if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') {
  1709.  
  1710. for (const [k, v] of Object.entries(_yt_player)) {
  1711.  
  1712. if (typeof v === 'function' && typeof v.prototype.clone === 'function'
  1713. && typeof v.prototype.get === 'function' && typeof v.prototype.set === 'function'
  1714.  
  1715. && typeof v.prototype.isEmpty === 'undefined' && typeof v.prototype.forEach === 'undefined'
  1716. && typeof v.prototype.clear === 'undefined'
  1717.  
  1718. ) {
  1719.  
  1720. key = k;
  1721.  
  1722. }
  1723.  
  1724. }
  1725.  
  1726. }
  1727.  
  1728. if (key) {
  1729.  
  1730. const ClassX = _yt_player[key];
  1731. _yt_player[key] = class extends ClassX {
  1732. constructor(...args) {
  1733.  
  1734. if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = '';
  1735. super(...args);
  1736.  
  1737. }
  1738. }
  1739. _yt_player[key].luX1Y = 1;
  1740. }
  1741.  
  1742. }
  1743. let s3 = Symbol();
  1744.  
  1745. generalRegister('deviceIsAudioOnly', s3, (p) => {
  1746. return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p)
  1747. }, {
  1748.  
  1749. get() {
  1750. return this[s3];
  1751. },
  1752. set(nv) {
  1753. if (typeof nv === 'boolean') this[s3] = true;
  1754. else this[s3] = undefined;
  1755. prepare();
  1756. return true;
  1757. },
  1758. enumerable: false,
  1759. configurable: true
  1760.  
  1761. });
  1762.  
  1763.  
  1764. let s1 = Symbol();
  1765. let s2 = Symbol();
  1766. Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', {
  1767. get() {
  1768. // console.log(501, this.constructor.prototype)
  1769. return undefined;
  1770. },
  1771. set(nv) {
  1772. return true;
  1773. },
  1774. enumerable: false,
  1775. configurable: true
  1776. });
  1777.  
  1778. Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', {
  1779. get() {
  1780. // console.log(502, this.constructor.prototype)
  1781. return this[s1];
  1782. },
  1783. set(nv) {
  1784. if (typeof nv === 'boolean') this[s1] = false;
  1785. else this[s1] = undefined;
  1786. return true;
  1787. },
  1788. enumerable: false,
  1789. configurable: true
  1790. });
  1791.  
  1792. Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', {
  1793. get() {
  1794. // console.log(503, this.constructor.prototype)
  1795. return this[s2];
  1796. },
  1797. set(nv) {
  1798. if (typeof nv === 'boolean') this[s2] = false;
  1799. else this[s2] = undefined;
  1800. return true;
  1801. },
  1802. enumerable: false,
  1803. configurable: true
  1804. });
  1805.  
  1806.  
  1807. const supportedFormatsConfig = () => {
  1808.  
  1809. function typeTest(type) {
  1810. if (typeof type === 'string' && type.startsWith('video/')) {
  1811. return false;
  1812. }
  1813. }
  1814.  
  1815. // return a custom MIME type checker that can defer to the original function
  1816. function makeModifiedTypeChecker(origChecker) {
  1817. // Check if a video type is allowed
  1818. return function (type) {
  1819. let res = undefined;
  1820. if (type === undefined) res = false;
  1821. else {
  1822. res = typeTest.call(this, type);
  1823. }
  1824. if (res === undefined) res = origChecker.apply(this, arguments);
  1825. return res;
  1826. };
  1827. }
  1828.  
  1829. // Override video element canPlayType() function
  1830. const proto = (HTMLVideoElement || 0).prototype;
  1831. if (proto && typeof proto.canPlayType == 'function') {
  1832. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  1833. }
  1834.  
  1835. // Override media source extension isTypeSupported() function
  1836. const mse = window.MediaSource;
  1837. // Check for MSE support before use
  1838. if (mse && typeof mse.isTypeSupported == 'function') {
  1839. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  1840. }
  1841.  
  1842. };
  1843.  
  1844. supportedFormatsConfig();
  1845. }
  1846.  
  1847. const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? (await GM.getValue("isEnable_aWsjF", true)) : null;
  1848. if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
  1849. if (isEnable) {
  1850. const element = document.createElement('button');
  1851. element.setAttribute('onclick', `(${pageInjectionCode})()`);
  1852. element.click();
  1853. }
  1854.  
  1855. GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
  1856. await GM.setValue("isEnable_aWsjF", !isEnable);
  1857. document.documentElement.setAttribute('forceRefresh032', '');
  1858. location.reload();
  1859. });
  1860.  
  1861. let messageCount = 0;
  1862. let busy = false;
  1863. window.addEventListener('message', (evt) => {
  1864.  
  1865. const v = ((evt || 0).data || 0).ZECxh;
  1866. if (typeof v === 'boolean') {
  1867. if (messageCount > 1e9) messageCount = 9;
  1868. const t = ++messageCount;
  1869. if (v && isEnable) {
  1870. requestAnimationFrame(async () => {
  1871. if (t !== messageCount) return;
  1872. if (busy) return;
  1873. busy = true;
  1874. if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
  1875. await GM.setValue("isEnable_aWsjF", !isEnable);
  1876. document.documentElement.setAttribute('forceRefresh032', '');
  1877. location.reload();
  1878. }
  1879. busy = false;
  1880. });
  1881. }
  1882. }
  1883.  
  1884. });
  1885.  
  1886.  
  1887. const pLoad = new Promise(resolve => {
  1888. if (document.readyState !== 'loading') {
  1889. resolve();
  1890. } else {
  1891. window.addEventListener("DOMContentLoaded", resolve, false);
  1892. }
  1893. });
  1894.  
  1895.  
  1896. function contextmenuInfoItemAppearedFn(target) {
  1897.  
  1898. const btn = target.closest('.ytp-menuitem[role="menuitem"]');
  1899. if (!btn) return;
  1900. if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return;
  1901. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1902. const newBtn = btn.cloneNode(true)
  1903. newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1904. newBtn.classList.add('audio-only-toggle-btn');
  1905. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1906. newBtn.addEventListener('click', async () => {
  1907. await GM.setValue("isEnable_aWsjF", !isEnable);
  1908. document.documentElement.setAttribute('forceRefresh032', '');
  1909. location.reload();
  1910. });
  1911. let t;
  1912. let h = 0;
  1913. t = btn.closest('.ytp-panel-menu[style*="height"]');
  1914. if (t) t.style.height = t.scrollHeight + 'px';
  1915. t = btn.closest('.ytp-panel[style*="height"]');
  1916. if (t) t.style.height = (h = t.scrollHeight) + 'px';
  1917. t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]');
  1918. if (t && h > 0) t.style.height = h + 'px';
  1919. }
  1920.  
  1921.  
  1922. function mobileMenuItemAppearedFn(target) {
  1923.  
  1924. const btn = target.closest('ytm-menu-item');
  1925. if (!btn) return;
  1926. if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return;
  1927. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1928. const newBtn = btn.cloneNode(true);
  1929. newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1930. newBtn.classList.add('audio-only-toggle-btn');
  1931. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1932. newBtn.addEventListener('click', async () => {
  1933. await GM.setValue("isEnable_aWsjF", !isEnable);
  1934. document.documentElement.setAttribute('forceRefresh032', '');
  1935. location.reload();
  1936. });
  1937. }
  1938.  
  1939.  
  1940. pLoad.then(() => {
  1941.  
  1942. document.addEventListener('animationstart', (evt) => {
  1943. const animationName = evt.animationName;
  1944. if (!animationName) return;
  1945.  
  1946. if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target);
  1947. if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target);
  1948.  
  1949. }, true);
  1950.  
  1951. const cssForEnabled = isEnable ? `
  1952.  
  1953. .html5-video-player {
  1954. background-color: black;
  1955. }
  1956.  
  1957. [style*="--audio-only-thumbnail-image"]{
  1958. background-image: var(--audio-only-thumbnail-image);
  1959. object-fit: contain;
  1960. background-position: center;
  1961. background-size: contain;
  1962. background-repeat: no-repeat;
  1963. }
  1964. .html5-video-player.ended-mode [style*="--audio-only-thumbnail-image"]{
  1965. background-image: none;
  1966. }
  1967.  
  1968. .html5-video-player.ytp-ce-shown .html5-video-container {
  1969. opacity: 0.5;
  1970. transition: opacity 0.5s;
  1971. }
  1972.  
  1973. ytd-video-preview #media-container div#player-container,
  1974. ytd-video-preview #media-container div#thumbnail-container{
  1975. transition: initial !important;
  1976. transition-duration:0ms !important;
  1977. transition-delay:0ms !important;
  1978. }
  1979. ytd-video-preview #media-container div#thumbnail-container{
  1980. /* pointer-events:none !important; */
  1981. opacity:0;
  1982. /* z-index:-1; */
  1983. }
  1984. ytd-video-preview #media-container div#player-container,
  1985. ytd-video-preview #media-container div#inline-preview-player{
  1986. background-color:transparent !important;
  1987. background-image:none !important;
  1988. }
  1989.  
  1990. #movie_player > .html5-video-container:not(:empty) {
  1991. box-sizing: border-box;
  1992. height: 100%;
  1993. }
  1994.  
  1995. `: "";
  1996.  
  1997. const style = document.createElement('style');
  1998. style.id = 'fm9v0';
  1999. style.textContent = `
  2000.  
  2001. ${cssForEnabled}
  2002.  
  2003. @keyframes mobileMenuItemAppeared {
  2004. 0% {
  2005. background-position-x: 3px;
  2006. }
  2007. 100% {
  2008. background-position-x: 4px;
  2009. }
  2010. }
  2011. ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type {
  2012. animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards;
  2013. }
  2014. @keyframes contextmenuInfoItemAppeared {
  2015. 0% {
  2016. background-position-x: 3px;
  2017. }
  2018. 100% {
  2019. background-position-x: 4px;
  2020. }
  2021. }
  2022. .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{
  2023. animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards;
  2024. }
  2025. #confirmDialog794 {
  2026. z-index:999999 !important;
  2027. display: none;
  2028. /* Hidden by default */
  2029. position: fixed;
  2030. /* Stay in place */
  2031. z-index: 1;
  2032. /* Sit on top */
  2033. left: 0;
  2034. top: 0;
  2035. width: 100%;
  2036. /* Full width */
  2037. height: 100%;
  2038. /* Full height */
  2039. overflow: auto;
  2040. /* Enable scroll if needed */
  2041. background-color: rgba(0,0,0,0.4);
  2042. /* Black w/ opacity */
  2043. }
  2044. #confirmDialog794 .confirm-box {
  2045. position:relative;
  2046. color: black;
  2047. z-index:999999 !important;
  2048. background-color: #fefefe;
  2049. margin: 15% auto;
  2050. /* 15% from the top and centered */
  2051. padding: 20px;
  2052. border: 1px solid #888;
  2053. width: 30%;
  2054. /* Could be more or less, depending on screen size */
  2055. box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  2056. }
  2057. #confirmDialog794 .confirm-buttons {
  2058. text-align: right;
  2059. }
  2060. #confirmDialog794 button {
  2061. margin-left: 10px;
  2062. }
  2063. `
  2064. document.head.appendChild(style);
  2065.  
  2066. if (false && isEnable) {
  2067. let mzId = 0;
  2068.  
  2069. let mz = 0;
  2070. const mof = async () => {
  2071. mzId && clearInterval(mzId);
  2072. if (mz > 1e9) mz = 9;
  2073. const mt = ++mz;
  2074.  
  2075. let q = document.querySelector('#video-preview > ytd-video-preview.style-scope.ytd-app');
  2076. if(!q) return;
  2077. if (q.hasAttribute('active') && !q.hasAttribute('hidden')) {
  2078.  
  2079. }else{
  2080. return;
  2081. }
  2082.  
  2083.  
  2084. let inlinePreviewPlayer = null;
  2085. const ss = [HTMLElement.prototype.querySelector.call(q, '#inline-preview-player')].filter(e=>e && !e.closest('[hidden]'));
  2086. if (ss && ss.length === 1) {
  2087. inlinePreviewPlayer = ss[0];
  2088. }
  2089. if(!inlinePreviewPlayer) return;
  2090.  
  2091. const f = ()=>{
  2092. if (mz !== mt || !(q.hasAttribute('active') && !q.hasAttribute('hidden')) || !(inlinePreviewPlayer && inlinePreviewPlayer.isConnected === true)) {
  2093. mzId && clearInterval(mzId);
  2094. mzId= 0;
  2095. return;
  2096. }
  2097.  
  2098. const s = inlinePreviewPlayer;
  2099. s.classList.remove('ytp-hide-inline-preview-progress-bar');
  2100. s.classList.remove('ytp-hide-inline-preview-audio-controls');
  2101. s.classList.add('ytp-show-inline-preview-progress-bar');
  2102. s.classList.add('ytp-show-inline-preview-audio-controls');
  2103. s.classList.remove('ytp-autohide');
  2104. if (q.hasAttribute('hide-volume-controls')) {
  2105. q.removeAttribute('hide-volume-controls')
  2106. }
  2107. if(s.classList.contains('playing-mode') && !q.hasAttribute('playing')){
  2108. q.setAttribute('playing','')
  2109. }
  2110. }
  2111. mzId = setInterval(f, 40);
  2112. f();
  2113.  
  2114. }
  2115. const mo = new MutationObserver(mof);
  2116. document.addEventListener('yt-navigate-finish', async function () {
  2117.  
  2118. for (const s of document.querySelectorAll('ytd-video-preview')) {
  2119. mo.observe(s, {
  2120. attributes: true,
  2121. attributeFilter: ["hidden", "active"],
  2122. attributeOldValue: false
  2123. });
  2124. mof();
  2125. }
  2126.  
  2127. }, false);
  2128. }
  2129. })
  2130.  
  2131.  
  2132. })();