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.1
  6. // @author CY Fung
  7. // @match https://www.youtube.com/*
  8. // @match https://www.youtube.com/embed/*
  9. // @match https://www.youtube-nocookie.com/embed/*
  10. // @match https://m.youtube.com/*
  11. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  12. // @icon https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/YouTube-Audio-Only.png
  13. // @grant GM_registerMenuCommand
  14. // @grant GM.setValue
  15. // @grant GM.getValue
  16. // @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(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. console.log(e)
  663. }
  664. };
  665. const triggerPlaying = async () => {
  666. await player_.pauseVideo();
  667. await player_.playVideo();
  668. };
  669. const seekToLiveHeadForLiveStream = async () => {
  670. try {
  671. await player_.seekToLiveHead();
  672. if ((await player_.isAtLiveHead()) === true) {
  673. await player_.seekToStreamTime();
  674. return true;
  675. }
  676. } catch (e) {
  677. console.log(e);
  678. }
  679. };
  680. const fixLiveAudioFn = async () => {
  681. if (audio.paused === true) {
  682. await player_.clearVideo(); // avoid error in live streaming
  683. await player_.clearQueue(); // avoid error in live streaming
  684. await delayPn(300);
  685. for (let i = 0; i < 3; i++) {
  686. if (audio.readyState === 0) {
  687. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  688. }
  689. }
  690. if (k === -1) {
  691. await refreshAllStaleEntitiesForNonReadyAudio();
  692. } else if (k === 3) {
  693. while (audio.readyState === 0) {
  694. await refreshAllStaleEntitiesForNonReadyAudio();
  695. await triggerPlaying();
  696. await delayPn(300);
  697. }
  698. }
  699. } else if (audio.paused === false) {
  700. if (!player_.isAtLiveHead()) {
  701. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  702. }
  703. while (audio.readyState === 0) {
  704. await refreshAllStaleEntitiesForNonReadyAudio();
  705. await triggerPlaying();
  706. await delayPn(300);
  707. }
  708. if (!player_.isAtLiveHead()) {
  709. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  710. }
  711. await refreshAllStaleEntitiesForNonReadyAudio();
  712. if (audio.readyState > 0 && audio.paused === true) {
  713. await triggerPlaying();
  714. }
  715. }
  716. }
  717. try {
  718. const ns23 = audio.networkState == 2 || audio.networkState == 3;
  719. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  720. await delayPn(200);
  721. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  722. await fixLiveAudioFn();
  723. }
  724. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  725. await seekToLiveHeadForLiveStream();
  726. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  727. await delayPn(60);
  728. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  729. await fixLiveAudioFn();
  730. }
  731. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  732. await seekToLiveHeadForLiveStream();
  733. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  734. await delayPn(60);
  735. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  736. await fixLiveAudioFn();
  737. }
  738. }
  739.  
  740. } catch (e) {
  741. console.log(e)
  742. }
  743.  
  744. };
  745.  
  746. // console.log(299, player_)
  747. const _onPlayerStateChange = (k) => {
  748. try {
  749. if (typeof k === 'number' && k === player_.getPlayerState()) {
  750.  
  751. const audio = document.querySelector('#player audio.video-stream.html5-main-video');
  752. if (audio) asyncStateChange(audio, k);
  753. }
  754. } catch (e) {
  755. console.log(e)
  756. }
  757. };
  758.  
  759. player_.addEventListener('onStateChange', _onPlayerStateChange);
  760. const state0 = player_.getPlayerState();
  761. if (typeof state0 === 'number') {
  762. _onPlayerStateChange(state0);
  763. }
  764.  
  765. player_.addEventListener('onVideoProgress', () => {
  766. updateLastActiveTimeAsync(player_);
  767. });
  768.  
  769. // console.log(1231)
  770.  
  771. if (SHOW_VIDEO_STATIC_IMAGE) {
  772.  
  773. let displayImage = '';
  774. let html5Container = null;
  775.  
  776.  
  777. const moviePlayer = document.querySelector('#movie_player .html5-video-container .video-stream.html5-main-video');
  778. if (moviePlayer) {
  779. html5Container = moviePlayer.closest('.html5-video-container');
  780. }
  781.  
  782. if (html5Container) {
  783.  
  784. const overlayImage = document.querySelector('#movie_player .ytp-cued-thumbnail-overlay-image[style]');
  785. if (overlayImage) {
  786.  
  787. const cStyle = window.getComputedStyle(overlayImage);
  788. const cssImageValue = cStyle.backgroundImage;
  789. if (cssImageValue && typeof cssImageValue === 'string' && cssImageValue.startsWith('url(')) {
  790. displayImage = cssImageValue;
  791.  
  792. }
  793.  
  794. }
  795.  
  796. if (!displayImage) {
  797.  
  798. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  799. let embedded_player_response = null;
  800. if (config_) {
  801. embedded_player_response = ((config_.PLAYER_VARS || 0).embedded_player_response || 0)
  802. }
  803. if (embedded_player_response && typeof embedded_player_response === 'string') {
  804.  
  805. let idx1 = embedded_player_response.indexOf('"defaultThumbnail"');
  806. let idx2 = idx1 >= 0 ? embedded_player_response.lastIndexOf('"defaultThumbnail"') : -1;
  807.  
  808. if (idx1 === idx2 && idx1 > 0) {
  809.  
  810. let bk = 0;
  811. let j = -1;
  812. for (let i = idx1; i < embedded_player_response.length; i++) {
  813. if (i > idx1 + 40 && bk === 0) {
  814. j = i;
  815. break;
  816. }
  817. let t = embedded_player_response.charAt(i);
  818. if (t === '{') bk++;
  819. else if (t === '}') bk--;
  820. }
  821.  
  822. if (j > idx1) {
  823.  
  824. let defaultThumbnailString = embedded_player_response.substring(idx1, j);
  825. let defaultThumbnailObject = null;
  826.  
  827. try {
  828. defaultThumbnailObject = JSON.parse(`{${defaultThumbnailString}}`);
  829.  
  830. } catch (e) { }
  831.  
  832. const thumbnails = ((defaultThumbnailObject.defaultThumbnail || 0).thumbnails || 0);
  833.  
  834. if (thumbnails && thumbnails.length >= 1) {
  835.  
  836. let thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  837.  
  838. if (thumbnailUrl && thumbnailUrl.length > 3) {
  839. displayImage = `url(${thumbnailUrl})`;
  840. }
  841. }
  842. }
  843.  
  844. }
  845.  
  846.  
  847. }
  848.  
  849.  
  850. }
  851.  
  852. if (displayImage) {
  853.  
  854. html5Container.style.setProperty('--audio-only-thumbnail-image', `${displayImage}`);
  855. } else {
  856. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  857. }
  858.  
  859. }
  860.  
  861.  
  862. }
  863.  
  864. })
  865.  
  866.  
  867. } else {
  868.  
  869. attachOneTimeEvent('yt-action', () => {
  870. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  871. ytConfigFix(config_);
  872. });
  873.  
  874. const setupAudioPlaying = (player00_) => {
  875. const player_ = player00_;
  876. if (!player_) return;
  877. if (player_.__audio544__) return;
  878. player_.__audio544__ = 1;
  879. // console.log(1233, player_)
  880. let ytdPlayerElement = null;
  881.  
  882. const stopAndReloadFn = async () => {
  883. let isLive = false;
  884. if (location.pathname === '/watch') {
  885. const liveBtn = document.querySelector('.ytp-live-badge.ytp-button');
  886. try {
  887. if (liveBtn && !liveBtn.closest('[hidden]') && (liveBtn.textContent || '').trim().length > 0) {
  888. isLive = true;
  889. }
  890. } catch (e) { }
  891. }
  892. if (isLive) {
  893. player_.destroy();
  894. location.replace(location.href);
  895. await delayPn(8000);
  896. } else {
  897. // await player_.stopVideo();
  898. // await player_.updateVideoData();
  899. // try{
  900. // await player_.refreshAllStaleEntities();
  901. // }catch(e){}
  902. // await player_.playVideo();
  903. }
  904. };
  905. const asyncStateChange = async (audio, k) => {
  906.  
  907. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  908. try {
  909. if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  910. } catch (e) {
  911. console.log(e)
  912. }
  913. };
  914. const triggerPlaying = async () => {
  915. await player_.cancelPlayback();
  916. await player_.pauseVideo();
  917. await player_.playVideo();
  918. };
  919. const seekToLiveHeadForLiveStream = async () => {
  920. try {
  921. await player_.seekToLiveHead();
  922. if ((await player_.isAtLiveHead()) === true) {
  923. await player_.seekToStreamTime();
  924. return true;
  925. }
  926. } catch (e) {
  927. console.log(e);
  928. }
  929. };
  930. const fixLiveAudioFn = async () => {
  931. if (stopAndReload) {
  932. stopAndReload = false;
  933. await stopAndReloadFn();
  934. }
  935. if (audio.paused === true) {
  936. await player_.clearVideo(); // avoid error in live streaming
  937. await player_.clearQueue(); // avoid error in live streaming
  938. await delayPn(300);
  939. for (let i = 0; i < 3; i++) {
  940. if (audio.readyState === 0) {
  941. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  942. }
  943. }
  944. if (k === -1) {
  945. await refreshAllStaleEntitiesForNonReadyAudio();
  946. } else if (k === 3) {
  947. while (audio.readyState === 0) {
  948. await refreshAllStaleEntitiesForNonReadyAudio();
  949. await triggerPlaying();
  950. await delayPn(300);
  951. }
  952. }
  953. } else if (audio.paused === false) {
  954. if (!player_.isAtLiveHead()) {
  955. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  956. }
  957. while (audio.readyState === 0) {
  958. await refreshAllStaleEntitiesForNonReadyAudio();
  959. await triggerPlaying();
  960. await delayPn(300);
  961. }
  962. if (!player_.isAtLiveHead()) {
  963. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  964. }
  965. await refreshAllStaleEntitiesForNonReadyAudio();
  966. if (audio.readyState > 0 && audio.paused === true) {
  967. await triggerPlaying();
  968. }
  969. }
  970. }
  971. try {
  972.  
  973. const ns23 = audio.networkState == 2 || audio.networkState == 3;
  974. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  975. await delayPn(200);
  976. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  977. await fixLiveAudioFn();
  978. }
  979. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  980. await seekToLiveHeadForLiveStream();
  981. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  982. await delayPn(60);
  983. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === false) {
  984. await fixLiveAudioFn();
  985. }
  986. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === true) {
  987. await seekToLiveHeadForLiveStream();
  988. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  989. await delayPn(60);
  990. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.muted === true) {
  991. await fixLiveAudioFn();
  992. }
  993. }
  994.  
  995. } catch (e) {
  996. console.log(e)
  997. }
  998.  
  999. };
  1000. let mid = 0;
  1001. const getAudioElement = () => {
  1002. if (!ytdPlayerElement) {
  1003. ytdPlayerElement = [...document.querySelectorAll('ytd-player')].filter(e => !e.closest('[hidden]'))[0]
  1004. }
  1005. const audio = ytdPlayerElement ? HTMLElement.prototype.querySelector.call(ytdPlayerElement, '.video-stream.html5-main-video') : null;
  1006. return audio;
  1007. }
  1008. const _onPlayerStateChange = (k_) => {
  1009. const k = k_;
  1010. const ps = player_.getPlayerState();
  1011. if (stopAndReload) {
  1012. stopAndReload = false;
  1013. const audio = getAudioElement();
  1014. if (audio) {
  1015. prrPipeline(async () => {
  1016. await prr.then();
  1017. await stopAndReloadFn();
  1018. });
  1019. }
  1020. }
  1021. if (typeof k === 'number' && k === ps) {
  1022. const audio = getAudioElement();
  1023. if (audio) {
  1024. if (mid > 1e9) mid = 9;
  1025. const t = ++mid;
  1026. prrPipeline(async () => {
  1027. if (t !== mid) return;
  1028. await prr.then();
  1029. if (t !== mid) return;
  1030. await asyncStateChange(audio, k);
  1031. });
  1032. }
  1033. }
  1034. };
  1035.  
  1036. player_.addEventListener('onStateChange', _onPlayerStateChange);
  1037. const state0 = player_.getPlayerState();
  1038. // console.log(221, state0)
  1039. if (typeof state0 === 'number') {
  1040. _onPlayerStateChange(state0);
  1041. }
  1042.  
  1043. player_.addEventListener('onVideoProgress', () => {
  1044. updateLastActiveTimeAsync(player_);
  1045. });
  1046.  
  1047. }
  1048.  
  1049. customElements.whenDefined('ytd-player').then(() => {
  1050. const dummy = document.querySelector('ytd-player') || document.createElement('ytd-player');
  1051. const cnt = insp(dummy);
  1052. const cProto = cnt.constructor.prototype;
  1053. cProto.createMainAppPlayer932_ = cProto.createMainAppPlayer_;
  1054. cProto.initPlayer932_ = cProto.initPlayer_;
  1055. cProto.createMainAppPlayer_ = function (a, b, c) {
  1056. let r = this.createMainAppPlayer932_(a, b, c);
  1057. try {
  1058. this.mainAppPlayer_.api.then(function (e) {
  1059. setupAudioPlaying(e);
  1060. })
  1061. } finally {
  1062. return r;
  1063. }
  1064. }
  1065. cProto.initPlayer_ = function (a) {
  1066. let r = this.initPlayer932_(a);
  1067. try {
  1068. r.then(() => {
  1069. setupAudioPlaying(this.player_);
  1070. })
  1071. } finally {
  1072. return r;
  1073. }
  1074. }
  1075. })
  1076.  
  1077. let useStopAndReload = location.pathname !== '/watch';
  1078. document.addEventListener('yt-navigate-start', () => {
  1079. prr = new PromiseExternal();
  1080. if (useStopAndReload) stopAndReload = true;
  1081. });
  1082.  
  1083. document.addEventListener('yt-navigate-cache', () => {
  1084. prr = new PromiseExternal();
  1085. if (useStopAndReload) stopAndReload = true;
  1086. });
  1087.  
  1088. document.addEventListener('yt-navigate-finish', () => {
  1089. prr.resolve();
  1090. });
  1091.  
  1092. }
  1093.  
  1094. } else if (location.origin === 'https://m.youtube.com') {
  1095.  
  1096. removeBottomOverlayForMobile = async (delay) => {
  1097.  
  1098.  
  1099. let closeBtnRenderer = document.querySelector('.ytm-bottom-sheet-overlay-renderer-close.icon-close');
  1100. if (closeBtnRenderer) {
  1101.  
  1102. const btn = closeBtnRenderer.querySelector('button');
  1103. const container = closeBtnRenderer.closest('#global-loader ~ .ytm-bottom-sheet-overlay-container');
  1104.  
  1105. if (container) {
  1106. container.style.visibility = 'collapse';
  1107. container.style.zIndex = '-1';
  1108. }
  1109. if (btn) {
  1110. if (delay) {
  1111. await delayPn(delay);
  1112. }
  1113. btn.click();
  1114. }
  1115. }
  1116.  
  1117. }
  1118.  
  1119.  
  1120. let lastPlayerInfoText = '';
  1121. let mz = 0;
  1122. onVideoChangeForMobile = async () => {
  1123.  
  1124.  
  1125. let html5Container = null;
  1126.  
  1127. const moviePlayer = document.querySelector('#player .html5-video-container .video-stream.html5-main-video');
  1128. if (moviePlayer) {
  1129. html5Container = moviePlayer.closest('.html5-video-container');
  1130. }
  1131. if (!html5Container) return;
  1132. let thumbnailUrl = '';
  1133.  
  1134. if (mz > 1e9) mz = 9;
  1135. let mt = ++mz;
  1136. const scriptText = await observablePromise(() => {
  1137. if (mt !== mz) return 1;
  1138. const t = document.querySelector('player-microformat-renderer.PlayerMicroformatRendererHost script[type="application/ld+json"]');
  1139. const tt = (t ? t.textContent : '') || '';
  1140. if (tt === lastPlayerInfoText) return;
  1141. return tt;
  1142. }).obtain();
  1143. if (typeof scriptText !== 'string') return; // 1
  1144. lastPlayerInfoText = scriptText;
  1145.  
  1146. if (!scriptText) return;
  1147.  
  1148.  
  1149. if (SHOW_VIDEO_STATIC_IMAGE) {
  1150.  
  1151. let idx1 = scriptText.indexOf('"thumbnailUrl"');
  1152. let idx2 = idx1 >= 0 ? scriptText.lastIndexOf('"thumbnailUrl"') : -1;
  1153.  
  1154. if (idx1 === idx2 && idx1 > 0) {
  1155.  
  1156. let bk = 0;
  1157. let j = -1;
  1158. for (let i = idx1; i < scriptText.length; i++) {
  1159. if (i > idx1 + 20 && bk === 0) {
  1160. j = i;
  1161. break;
  1162. }
  1163. let t = scriptText.charAt(i);
  1164. if (t === '[') bk++;
  1165. else if (t === ']') bk--;
  1166. else if (t === '{') bk++;
  1167. else if (t === '}') bk--;
  1168. }
  1169.  
  1170.  
  1171. if (j > idx1) {
  1172.  
  1173. let thumbnailUrlString = scriptText.substring(idx1, j);
  1174. let thumbnailUrlObject = null;
  1175.  
  1176. try {
  1177. thumbnailUrlObject = JSON.parse(`{${thumbnailUrlString}}`);
  1178.  
  1179. } catch (e) { }
  1180.  
  1181. const thumbnails = thumbnailUrlObject.thumbnailUrl;
  1182.  
  1183. if (thumbnails && thumbnails.length >= 1 && typeof thumbnails[0] === 'string') {
  1184. if (thumbnails[0] && thumbnails[0].length > 3) {
  1185. thumbnailUrl = thumbnails[0];
  1186. }
  1187. }
  1188. }
  1189.  
  1190. }
  1191.  
  1192. // const ytipr = (typeof ytInitialPlayerResponse !== 'undefined' ? ytInitialPlayerResponse : null) || 0;
  1193.  
  1194. // const thumbnails = (((ytipr.videoDetails || 0).thumbnail || 0).thumbnails || 0);
  1195.  
  1196. // if (thumbnails && thumbnails.length >= 1) {
  1197. // thumbnailUrl = getThumbnailUrlFromThumbnails(thumbnails);
  1198.  
  1199. // }
  1200. if (thumbnailUrl && typeof thumbnailUrl === 'string') {
  1201. html5Container.style.setProperty('--audio-only-thumbnail-image', `url(${thumbnailUrl})`);
  1202. } else {
  1203. html5Container.style.removeProperty('--audio-only-thumbnail-image')
  1204. }
  1205.  
  1206. }
  1207.  
  1208.  
  1209. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(40);
  1210.  
  1211. await delayPn(80);
  1212. const audio = moviePlayer;
  1213. if (audio && audio.muted === true && audio.isConnected === true && audio.readyState >= 0 && audio.networkState >= 2 && audio.paused === false) {
  1214. await audio.click();
  1215. }
  1216.  
  1217. }
  1218.  
  1219. let player0 = null;
  1220. let mgg = null;
  1221. const mff = function (e) {
  1222. if (!player0) {
  1223. if (e && typeof ((e || 0).target || 0).getPlayerState === 'function') {
  1224. player0 = e.target
  1225. if (mgg) mgg();
  1226. }
  1227. }
  1228.  
  1229.  
  1230. // if (SHOW_VIDEO_STATIC_IMAGE && (e.type === 'player-state-change' || e.type === 'video-data-change')) {
  1231.  
  1232. // onVideoChangeForMobile();
  1233. // }
  1234.  
  1235. }
  1236.  
  1237. document.addEventListener('player-initialized', mff, true);
  1238. document.addEventListener('player-state-change', mff, true);
  1239. document.addEventListener('player-ad-state-change', mff, true);
  1240. document.addEventListener('player-detailed-error', mff, true);
  1241. document.addEventListener('player-error', mff, true);
  1242. document.addEventListener('on-play-autonav-video', mff, true);
  1243. document.addEventListener('on-play-previous-autonav-video', mff, true);
  1244. document.addEventListener('player-fullscreen-change', mff, true);
  1245. document.addEventListener('player-fullscreen-toggled', mff, true);
  1246. document.addEventListener('player-dom-paused', mff, true);
  1247. document.addEventListener('yt-show-toast', mff, true);
  1248. document.addEventListener('yt-innertube-command', mff, true);
  1249. document.addEventListener('yt-update-c3-companion', mff, true);
  1250. document.addEventListener('video-data-change', mff, true);
  1251. document.addEventListener('video-progress', mff, true);
  1252. document.addEventListener('local-media-change', mff, true);
  1253.  
  1254.  
  1255. let tc = false;
  1256. // let pw = null;
  1257. (async () => {
  1258.  
  1259. let player__;
  1260. let elm;
  1261.  
  1262. const getAudioElement = () => {
  1263. if (!elm) {
  1264. elm = player__;
  1265. }
  1266. const audio = elm ? HTMLElement.prototype.querySelector.call(elm, '.video-stream.html5-main-video') : null;
  1267. return audio;
  1268. }
  1269.  
  1270. const asyncStateChange = async (audio, k) => {
  1271. const player_ = player__;
  1272. if (!player_) return;
  1273. if (typeof player_.getPlayerState !== 'function') return;
  1274.  
  1275. const refreshAllStaleEntitiesForNonReadyAudio = async () => {
  1276. // try {
  1277. // if (audio.readyState == 0) await player_.refreshAllStaleEntities();
  1278. // } catch (e) {
  1279. // console.log(e)
  1280. // }
  1281. };
  1282. const triggerPlaying = async () => {
  1283. await player_.cancelPlayback();
  1284. await player_.pauseVideo();
  1285. await player_.playVideo();
  1286. };
  1287. const seekToLiveHeadForLiveStream = async () => {
  1288. try {
  1289. await player_.seekToLiveHead();
  1290. if ((await player_.isAtLiveHead()) === true) {
  1291. await player_.seekToStreamTime();
  1292. return true;
  1293. }
  1294. } catch (e) {
  1295. console.log(e);
  1296. }
  1297. };
  1298. const fixLiveAudioFn = async () => {
  1299. if (audio.paused === true) {
  1300. await player_.clearVideo(); // avoid error in live streaming
  1301. await player_.clearQueue(); // avoid error in live streaming
  1302. await delayPn(300);
  1303. for (let i = 0; i < 3; i++) {
  1304. if (audio.readyState === 0) {
  1305. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1306. }
  1307. }
  1308. if (k === -1) {
  1309. await refreshAllStaleEntitiesForNonReadyAudio();
  1310. } else if (k === 3) {
  1311. while (audio.readyState === 0) {
  1312. await refreshAllStaleEntitiesForNonReadyAudio();
  1313. await triggerPlaying();
  1314. await delayPn(300);
  1315. }
  1316. // console.log(8809,audio.readyState)
  1317. }
  1318. } else if (audio.paused === false) {
  1319. if (!player_.isAtLiveHead()) {
  1320. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1321. }
  1322. while (audio.readyState === 0) {
  1323. await refreshAllStaleEntitiesForNonReadyAudio();
  1324. await triggerPlaying();
  1325. await delayPn(300);
  1326. }
  1327. if (!player_.isAtLiveHead()) {
  1328. if (await seekToLiveHeadForLiveStream()) await delayPn(60);
  1329. }
  1330. await refreshAllStaleEntitiesForNonReadyAudio();
  1331. if (audio.readyState > 0 && audio.paused === true) {
  1332. await triggerPlaying();
  1333. }
  1334. }
  1335.  
  1336. }
  1337. try {
  1338.  
  1339. const ns23 = audio.networkState == 2 || audio.networkState == 3
  1340. // console.log(127001, k, player_.getPlayerState(), audio.readyState, ns23, audio.muted)
  1341.  
  1342.  
  1343. if (removeBottomOverlayForMobile) await removeBottomOverlayForMobile(300);
  1344.  
  1345. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState > 0 && ns23 && audio.muted === true) {
  1346. tc = true;
  1347. }
  1348. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1349. await delayPn(200);
  1350. if (k === -1 && player_.getPlayerState() === -1 && audio.readyState === 0 && ns23) {
  1351. // console.log(8806)
  1352. await fixLiveAudioFn();
  1353. }
  1354. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState === 1 && ns23 && audio.muted === false) {
  1355. await seekToLiveHeadForLiveStream();
  1356. } else if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23) {
  1357. await delayPn(60);
  1358. if (k === 3 && player_.getPlayerState() === 3 && audio.readyState == 0 && ns23 && audio.paused === false) {
  1359. // console.log(8807)
  1360. await fixLiveAudioFn();
  1361. }
  1362.  
  1363. }
  1364.  
  1365. } catch (e) {
  1366. console.log(e)
  1367. }
  1368.  
  1369. };
  1370. const _onPlayerStateChange = (e) => {
  1371. if (e && (e || 0).target) {
  1372. player__ = e.target
  1373. }
  1374. const player_ = player__;
  1375. try {
  1376. if (!player_) return;
  1377. let k = null;
  1378. if (e && e.detail && e.detail.state) {
  1379. k = e.detail.state
  1380. }
  1381. if (typeof player_.getPlayerState === 'function' && typeof k === 'number' && k === player_.getPlayerState()) {
  1382. const audio = getAudioElement();
  1383. if (audio) asyncStateChange(audio, k);
  1384. }
  1385. } catch (e) {
  1386. console.log(e)
  1387. }
  1388. };
  1389.  
  1390. let idleAudioActivatePending = false;
  1391.  
  1392. const _onVideoProgress = (e) => {
  1393. if (e && (e || 0).target) {
  1394. player__ = e.target
  1395. }
  1396. const player_ = player__;
  1397. if (!player_) return;
  1398. updateLastActiveTimeAsync(player_);
  1399. if (tc) {
  1400. tc = false;
  1401. if (!idleAudioActivatePending) {
  1402. idleAudioActivatePending = true;
  1403. }
  1404. }
  1405. };
  1406.  
  1407. mgg = function () {
  1408. const player_ = player0;
  1409. if (player_) {
  1410. const state0 = player_.getPlayerState();
  1411. if (typeof state0 === 'number') {
  1412. _onPlayerStateChange({ type: 'player-state-change', target: player_, detail: { state: state0 } });
  1413. }
  1414. }
  1415. }
  1416.  
  1417. document.addEventListener('player-state-change', _onPlayerStateChange, true);
  1418.  
  1419. document.addEventListener('video-progress', _onVideoProgress, true);
  1420.  
  1421. })();
  1422.  
  1423. // document.addEventListener('DOMContentLoaded', (evt) => {
  1424. // const mo = new MutationObserver((mutations)=>{
  1425. // console.log(5899, mutations)
  1426. // });
  1427. // mo.observe(document, {subtree: true, childList: true})
  1428. // })
  1429.  
  1430. // window.addEventListener('onReady', (evt) => {
  1431. // console.log(6811)
  1432. // }, true);
  1433.  
  1434. // window.addEventListener('localmediachange', (evt) => {
  1435. // console.log(6812)
  1436. // }, true);
  1437.  
  1438. // window.addEventListener('onVideoDataChange', (evt) => {
  1439. // console.log(6813)
  1440. // }, true);
  1441.  
  1442. window.addEventListener('state-navigateend', async (evt) => {
  1443.  
  1444.  
  1445. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1446. ytConfigFix(config_);
  1447.  
  1448. try {
  1449. if (clickLockFn && clickTarget) {
  1450.  
  1451. let a = HTMLElement.prototype.querySelector.call(clickTarget, '.video-stream.html5-main-video');
  1452. if (!a) return;
  1453.  
  1454. if (a.muted === true && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1455.  
  1456. const pr = new Promise(resolve => {
  1457.  
  1458. document.addEventListener('player-state-change', resolve, { once: true, passive: true, capture: false });
  1459.  
  1460. }).then();
  1461.  
  1462. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1463. await delayPn(1);
  1464.  
  1465. if (a.muted === false && a.__spfgs__ !== true && a.paused === true && a.networkState === 0 && a.readyState === 0) {
  1466. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1467. await delayPn(1);
  1468. }
  1469.  
  1470. delayRun(pr);
  1471.  
  1472. }
  1473.  
  1474. }
  1475.  
  1476. } catch (e) { console.log(e) }
  1477.  
  1478.  
  1479. }, false);
  1480.  
  1481.  
  1482.  
  1483. // document.addEventListener('volumechange', (evt) => {
  1484. // console.log('volumechange')
  1485. // }, true)
  1486. // document.addEventListener('play', (evt) => {
  1487. // console.log('play')
  1488. // }, true)
  1489.  
  1490.  
  1491. // document.addEventListener('player-initialized', (evt) => {
  1492. // console.log(evt.type)
  1493. // }, true)
  1494. // document.addEventListener('renderer-module-load-start', (evt) => {
  1495. // console.log(evt.type)
  1496. // }, true)
  1497. // document.addEventListener('video-data-change', (evt) => {
  1498. // console.log(evt.type)
  1499. // }, true)
  1500. // document.addEventListener('player-state-change', (evt) => {
  1501. // console.log(evt.type)
  1502. // }, true)
  1503. // document.addEventListener('updateui', (evt) => {
  1504. // console.log(evt.type)
  1505. // }, true)
  1506. // document.addEventListener('renderer-module-load-end', (evt) => {
  1507. // console.log(evt.type)
  1508. // }, true)
  1509.  
  1510. // document.addEventListener('player-autonav-pause', (evt) => {
  1511. // console.log(evt.type)
  1512. // }, true)
  1513.  
  1514.  
  1515.  
  1516. // document.addEventListener('player-ad-state-change', (evt) => {
  1517. // console.log(evt.type)
  1518. // }, true)
  1519.  
  1520. // document.addEventListener('player-detailed-error', (evt) => {
  1521. // console.log(evt.type)
  1522. // }, true)
  1523.  
  1524. // document.addEventListener('player-error', (evt) => {
  1525. // console.log(evt.type)
  1526. // }, true)
  1527.  
  1528. // document.addEventListener('on-play-autonav-video', (evt) => {
  1529. // console.log(evt.type)
  1530. // }, true)
  1531.  
  1532. // document.addEventListener('on-play-previous-autonav-video', (evt) => {
  1533. // console.log(evt.type)
  1534. // }, true)
  1535.  
  1536. // document.addEventListener('player-fullscreen-change', (evt) => {
  1537. // console.log(evt.type)
  1538. // }, true)
  1539.  
  1540. // document.addEventListener('player-fullscreen-toggled', (evt) => {
  1541. // console.log(evt.type)
  1542. // }, true)
  1543.  
  1544. // document.addEventListener('player-dom-paused', (evt) => {
  1545. // console.log(evt.type)
  1546. // }, true)
  1547.  
  1548. // document.addEventListener('yt-show-toast', (evt) => {
  1549. // console.log(evt.type)
  1550. // }, true)
  1551. // document.addEventListener('yt-innertube-command', (evt) => {
  1552. // console.log(evt.type)
  1553. // }, true)
  1554. // document.addEventListener('yt-update-c3-companion', (evt) => {
  1555. // console.log(evt.type)
  1556. // }, true)
  1557. // document.addEventListener('video-progress', (evt) => {
  1558. // // console.log(evt.type)
  1559. // }, true)
  1560. // document.addEventListener('localmediachange', (evt) => {
  1561. // console.log(evt.type)
  1562. // }, true)
  1563.  
  1564.  
  1565.  
  1566. // window.addEventListener('player-initialized', (evt) => {
  1567. // console.log(evt.type)
  1568. // }, true)
  1569. // window.addEventListener('renderer-module-load-start', (evt) => {
  1570. // console.log(evt.type)
  1571. // }, true)
  1572. // window.addEventListener('video-data-change', (evt) => {
  1573. // console.log(evt.type)
  1574. // }, true)
  1575. // window.addEventListener('player-state-change', (evt) => {
  1576. // console.log(evt.type)
  1577. // }, true)
  1578. // window.addEventListener('updateui', (evt) => {
  1579. // console.log(evt.type)
  1580. // }, true)
  1581. // window.addEventListener('renderer-module-load-end', (evt) => {
  1582. // console.log(evt.type)
  1583. // }, true)
  1584.  
  1585. // window.addEventListener('player-autonav-pause', (evt) => {
  1586. // console.log(evt.type)
  1587. // }, true)
  1588.  
  1589.  
  1590.  
  1591. // window.addEventListener('player-ad-state-change', (evt) => {
  1592. // console.log(evt.type)
  1593. // }, true)
  1594.  
  1595. // window.addEventListener('player-detailed-error', (evt) => {
  1596. // console.log(evt.type)
  1597. // }, true)
  1598.  
  1599. // window.addEventListener('player-error', (evt) => {
  1600. // console.log(evt.type)
  1601. // }, true)
  1602.  
  1603. // window.addEventListener('on-play-autonav-video', (evt) => {
  1604. // console.log(evt.type)
  1605. // }, true)
  1606.  
  1607. // window.addEventListener('on-play-previous-autonav-video', (evt) => {
  1608. // console.log(evt.type)
  1609. // }, true)
  1610.  
  1611. // window.addEventListener('player-fullscreen-change', (evt) => {
  1612. // console.log(evt.type)
  1613. // }, true)
  1614.  
  1615. // window.addEventListener('player-fullscreen-toggled', (evt) => {
  1616. // console.log(evt.type)
  1617. // }, true)
  1618.  
  1619. // window.addEventListener('player-dom-paused', (evt) => {
  1620. // console.log(evt.type)
  1621. // }, true)
  1622.  
  1623. // window.addEventListener('yt-show-toast', (evt) => {
  1624. // console.log(evt.type)
  1625. // }, true)
  1626. // window.addEventListener('yt-innertube-command', (evt) => {
  1627. // console.log(evt.type)
  1628. // }, true)
  1629. // window.addEventListener('yt-update-c3-companion', (evt) => {
  1630. // console.log(evt.type)
  1631. // }, true)
  1632. // window.addEventListener('video-progress', (evt) => {
  1633. // // console.log(evt.type)
  1634. // }, true)
  1635. // window.addEventListener('localmediachange', (evt) => {
  1636. // console.log(evt.type)
  1637. // }, true)
  1638.  
  1639.  
  1640.  
  1641. // document.addEventListener('player-error', (evt) => {
  1642. // console.log(3001, evt.type, evt)
  1643. // }, true)
  1644. // document.addEventListener('player-detailed-error', (evt) => {
  1645. // console.log(3002, evt.type, evt)
  1646. // }, true)
  1647.  
  1648.  
  1649.  
  1650. async function delayRun(pr) {
  1651.  
  1652. let q = document.querySelector('#movie_player');
  1653. if (!q) return;
  1654. let a = document.querySelector('.video-stream.html5-main-video');
  1655. if (!a) return;
  1656.  
  1657. await pr.then();
  1658.  
  1659. if (fa !== 1) {
  1660. return;
  1661. } else if (a.muted === true) {
  1662. return;
  1663. } else if (a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1664. if (a.paused === false) return;
  1665. } else {
  1666. return;
  1667. }
  1668.  
  1669. if (document.querySelector('.player-controls-content')) return;
  1670.  
  1671. if (a.paused === true && a.muted === false && a.readyState === 0 && a.networkState === 2) {
  1672.  
  1673. clickLockFn.call(clickTarget, mockEvent({ type: 'click', target: clickTarget, detail: 1 }));
  1674.  
  1675. }
  1676.  
  1677. if (a.paused === true && a.muted === false && a.networkState === 2 && a.readyState === 0) {
  1678.  
  1679. if (typeof clickTarget.seekToLiveHead === 'function') await clickTarget.seekToLiveHead();
  1680. if (typeof clickTarget.isAtLiveHead === 'function' && (await clickTarget.isAtLiveHead()) === true) {
  1681. if (typeof clickTarget.seekToStreamTime === 'function') await clickTarget.seekToStreamTime();
  1682. }
  1683. }
  1684.  
  1685. }
  1686.  
  1687. durationchangeForMobile = true;
  1688.  
  1689. }
  1690.  
  1691. attachOneTimeEvent('yt-action', function () {
  1692. const config_ = typeof yt !== 'undefined' ? (yt || 0).config_ : 0;
  1693. ytConfigFix(config_);
  1694. });
  1695.  
  1696. let prepared = false;
  1697. function prepare() {
  1698. if (prepared) return;
  1699. prepared = true;
  1700.  
  1701. if (typeof _yt_player !== 'undefined' && _yt_player && typeof _yt_player === 'object') {
  1702.  
  1703. for (const [k, v] of Object.entries(_yt_player)) {
  1704.  
  1705. if (typeof v === 'function' && typeof v.prototype.clone === 'function'
  1706. && typeof v.prototype.get === 'function' && typeof v.prototype.set === 'function'
  1707.  
  1708. && typeof v.prototype.isEmpty === 'undefined' && typeof v.prototype.forEach === 'undefined'
  1709. && typeof v.prototype.clear === 'undefined'
  1710.  
  1711. ) {
  1712.  
  1713. key = k;
  1714.  
  1715. }
  1716.  
  1717. }
  1718.  
  1719. }
  1720.  
  1721. if (key) {
  1722.  
  1723. const ClassX = _yt_player[key];
  1724. _yt_player[key] = class extends ClassX {
  1725. constructor(...args) {
  1726.  
  1727. if (typeof args[0] === 'string' && args[0].startsWith('http://')) args[0] = '';
  1728. super(...args);
  1729.  
  1730. }
  1731. }
  1732. _yt_player[key].luX1Y = 1;
  1733. }
  1734.  
  1735. }
  1736. let s3 = Symbol();
  1737.  
  1738. generalRegister('deviceIsAudioOnly', s3, (p) => {
  1739. return typeof p.getPlayerType === 'function' && typeof p.getVideoEmbedCode === 'function' && typeof p.getVideoUrl === 'function' && !p.onCueRangeEnter && !p.getVideoData && !('ATTRIBUTE_NODE' in p)
  1740. }, {
  1741.  
  1742. get() {
  1743. return this[s3];
  1744. },
  1745. set(nv) {
  1746. if (typeof nv === 'boolean') this[s3] = true;
  1747. else this[s3] = undefined;
  1748. prepare();
  1749. return true;
  1750. },
  1751. enumerable: false,
  1752. configurable: true
  1753.  
  1754. });
  1755.  
  1756.  
  1757. let s1 = Symbol();
  1758. let s2 = Symbol();
  1759. Object.defineProperty(Object.prototype, 'defraggedFromSubfragments', {
  1760. get() {
  1761. // console.log(501, this.constructor.prototype)
  1762. return undefined;
  1763. },
  1764. set(nv) {
  1765. return true;
  1766. },
  1767. enumerable: false,
  1768. configurable: true
  1769. });
  1770.  
  1771. Object.defineProperty(Object.prototype, 'hasSubfragmentedFmp4', {
  1772. get() {
  1773. // console.log(502, this.constructor.prototype)
  1774. return this[s1];
  1775. },
  1776. set(nv) {
  1777. if (typeof nv === 'boolean') this[s1] = false;
  1778. else this[s1] = undefined;
  1779. return true;
  1780. },
  1781. enumerable: false,
  1782. configurable: true
  1783. });
  1784.  
  1785. Object.defineProperty(Object.prototype, 'hasSubfragmentedWebm', {
  1786. get() {
  1787. // console.log(503, this.constructor.prototype)
  1788. return this[s2];
  1789. },
  1790. set(nv) {
  1791. if (typeof nv === 'boolean') this[s2] = false;
  1792. else this[s2] = undefined;
  1793. return true;
  1794. },
  1795. enumerable: false,
  1796. configurable: true
  1797. });
  1798.  
  1799.  
  1800. const supportedFormatsConfig = () => {
  1801.  
  1802. function typeTest(type) {
  1803. if (typeof type === 'string' && type.startsWith('video/')) {
  1804. return false;
  1805. }
  1806. }
  1807.  
  1808. // return a custom MIME type checker that can defer to the original function
  1809. function makeModifiedTypeChecker(origChecker) {
  1810. // Check if a video type is allowed
  1811. return function (type) {
  1812. let res = undefined;
  1813. if (type === undefined) res = false;
  1814. else {
  1815. res = typeTest.call(this, type);
  1816. }
  1817. if (res === undefined) res = origChecker.apply(this, arguments);
  1818. return res;
  1819. };
  1820. }
  1821.  
  1822. // Override video element canPlayType() function
  1823. const proto = (HTMLVideoElement || 0).prototype;
  1824. if (proto && typeof proto.canPlayType == 'function') {
  1825. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  1826. }
  1827.  
  1828. // Override media source extension isTypeSupported() function
  1829. const mse = window.MediaSource;
  1830. // Check for MSE support before use
  1831. if (mse && typeof mse.isTypeSupported == 'function') {
  1832. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  1833. }
  1834.  
  1835. };
  1836.  
  1837. supportedFormatsConfig();
  1838. }
  1839.  
  1840. const isEnable = (typeof GM !== 'undefined' && typeof GM.getValue === 'function') ? (await GM.getValue("isEnable_aWsjF", true)) : null;
  1841. if (typeof isEnable !== 'boolean') throw new DOMException("Please Update your browser", "NotSupportedError");
  1842. if (isEnable) {
  1843. const element = document.createElement('button');
  1844. element.setAttribute('onclick', `(${pageInjectionCode})()`);
  1845. element.click();
  1846. }
  1847.  
  1848. GM_registerMenuCommand(`Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`, async function () {
  1849. await GM.setValue("isEnable_aWsjF", !isEnable);
  1850. document.documentElement.setAttribute('forceRefresh032', '');
  1851. location.reload();
  1852. });
  1853.  
  1854. let messageCount = 0;
  1855. let busy = false;
  1856. window.addEventListener('message', (evt) => {
  1857.  
  1858. const v = ((evt || 0).data || 0).ZECxh;
  1859. if (typeof v === 'boolean') {
  1860. if (messageCount > 1e9) messageCount = 9;
  1861. const t = ++messageCount;
  1862. if (v && isEnable) {
  1863. requestAnimationFrame(async () => {
  1864. if (t !== messageCount) return;
  1865. if (busy) return;
  1866. busy = true;
  1867. if (await confirm("Livestream is detected. Press OK to disable YouTube Audio Mode.")) {
  1868. await GM.setValue("isEnable_aWsjF", !isEnable);
  1869. document.documentElement.setAttribute('forceRefresh032', '');
  1870. location.reload();
  1871. }
  1872. busy = false;
  1873. });
  1874. }
  1875. }
  1876.  
  1877. });
  1878.  
  1879.  
  1880. const pLoad = new Promise(resolve => {
  1881. if (document.readyState !== 'loading') {
  1882. resolve();
  1883. } else {
  1884. window.addEventListener("DOMContentLoaded", resolve, false);
  1885. }
  1886. });
  1887.  
  1888.  
  1889. function contextmenuInfoItemAppearedFn(target) {
  1890.  
  1891. const btn = target.closest('.ytp-menuitem[role="menuitem"]');
  1892. if (!btn) return;
  1893. if (btn.parentNode.querySelector('.ytp-menuitem[role="menuitem"].audio-only-toggle-btn')) return;
  1894. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1895. const newBtn = btn.cloneNode(true)
  1896. newBtn.querySelector('.ytp-menuitem-label').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1897. newBtn.classList.add('audio-only-toggle-btn');
  1898. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1899. newBtn.addEventListener('click', async () => {
  1900. await GM.setValue("isEnable_aWsjF", !isEnable);
  1901. document.documentElement.setAttribute('forceRefresh032', '');
  1902. location.reload();
  1903. });
  1904. let t;
  1905. let h = 0;
  1906. t = btn.closest('.ytp-panel-menu[style*="height"]');
  1907. if (t) t.style.height = t.scrollHeight + 'px';
  1908. t = btn.closest('.ytp-panel[style*="height"]');
  1909. if (t) t.style.height = (h = t.scrollHeight) + 'px';
  1910. t = btn.closest('.ytp-popup.ytp-contextmenu[style*="height"]');
  1911. if (t && h > 0) t.style.height = h + 'px';
  1912. }
  1913.  
  1914.  
  1915. function mobileMenuItemAppearedFn(target) {
  1916.  
  1917. const btn = target.closest('ytm-menu-item');
  1918. if (!btn) return;
  1919. if (btn.parentNode.querySelector('ytm-menu-item.audio-only-toggle-btn')) return;
  1920. document.documentElement.classList.add('with-audio-only-toggle-btn');
  1921. const newBtn = btn.cloneNode(true);
  1922. newBtn.querySelector('.menu-item-button').textContent = `Turn ${isEnable ? 'OFF' : 'ON'} YouTube Audio Mode`;
  1923. newBtn.classList.add('audio-only-toggle-btn');
  1924. btn.parentNode.insertBefore(newBtn, btn.nextSibling);
  1925. newBtn.addEventListener('click', async () => {
  1926. await GM.setValue("isEnable_aWsjF", !isEnable);
  1927. document.documentElement.setAttribute('forceRefresh032', '');
  1928. location.reload();
  1929. });
  1930. }
  1931.  
  1932.  
  1933. pLoad.then(() => {
  1934.  
  1935. document.addEventListener('animationstart', (evt) => {
  1936. const animationName = evt.animationName;
  1937. if (!animationName) return;
  1938.  
  1939. if (animationName === 'contextmenuInfoItemAppeared') contextmenuInfoItemAppearedFn(evt.target);
  1940. if (animationName === 'mobileMenuItemAppeared') mobileMenuItemAppearedFn(evt.target);
  1941.  
  1942. }, true);
  1943.  
  1944.  
  1945. const style = document.createElement('style');
  1946. style.id = 'fm9v0';
  1947. style.textContent = `
  1948.  
  1949. .html5-video-player {
  1950. background-color: black;
  1951. }
  1952.  
  1953. [style*="--audio-only-thumbnail-image"]{
  1954. background-image: var(--audio-only-thumbnail-image);
  1955. object-fit: contain;
  1956. background-position: center;
  1957. background-size: contain;
  1958. background-repeat: no-repeat;
  1959. }
  1960.  
  1961. /* #movie_player > .ytp-iv-video-content {
  1962. pointer-events: none; // allow clicking
  1963. } */
  1964.  
  1965. #movie_player > .html5-video-container:not(:empty) {
  1966. box-sizing: border-box;
  1967. height: 100%;
  1968. }
  1969.  
  1970. @keyframes mobileMenuItemAppeared {
  1971. 0% {
  1972. background-position-x: 3px;
  1973. }
  1974. 100% {
  1975. background-position-x: 4px;
  1976. }
  1977. }
  1978. ytm-select.player-speed-settings ~ ytm-menu-item:last-of-type {
  1979. animation: mobileMenuItemAppeared 1ms linear 0s 1 normal forwards;
  1980. }
  1981. @keyframes contextmenuInfoItemAppeared {
  1982. 0% {
  1983. background-position-x: 3px;
  1984. }
  1985. 100% {
  1986. background-position-x: 4px;
  1987. }
  1988. }
  1989. .ytp-contextmenu .ytp-menuitem[role="menuitem"] path[d^="M22 34h4V22h-4v12zm2-30C12.95"]{
  1990. animation: contextmenuInfoItemAppeared 1ms linear 0s 1 normal forwards;
  1991. }
  1992. #confirmDialog794 {
  1993. z-index:999999 !important;
  1994. display: none;
  1995. /* Hidden by default */
  1996. position: fixed;
  1997. /* Stay in place */
  1998. z-index: 1;
  1999. /* Sit on top */
  2000. left: 0;
  2001. top: 0;
  2002. width: 100%;
  2003. /* Full width */
  2004. height: 100%;
  2005. /* Full height */
  2006. overflow: auto;
  2007. /* Enable scroll if needed */
  2008. background-color: rgba(0,0,0,0.4);
  2009. /* Black w/ opacity */
  2010. }
  2011. #confirmDialog794 .confirm-box {
  2012. position:relative;
  2013. color: black;
  2014. z-index:999999 !important;
  2015. background-color: #fefefe;
  2016. margin: 15% auto;
  2017. /* 15% from the top and centered */
  2018. padding: 20px;
  2019. border: 1px solid #888;
  2020. width: 30%;
  2021. /* Could be more or less, depending on screen size */
  2022. box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  2023. }
  2024. #confirmDialog794 .confirm-buttons {
  2025. text-align: right;
  2026. }
  2027. #confirmDialog794 button {
  2028. margin-left: 10px;
  2029. }
  2030. `
  2031. document.head.appendChild(style);
  2032. })
  2033.  
  2034.  
  2035. })();