Smooth YouTube livestream

5/11/2025, 9:27:12 PM

  1. // ==UserScript==
  2. // @name Smooth YouTube livestream
  3. // @namespace UserScripts
  4. // @version 0.1.3
  5. // @license MIT License
  6. // @match https://www.youtube.com/*
  7. // @grant none
  8. // @author -
  9. // @description 5/11/2025, 9:27:12 PM
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (() => {
  14.  
  15.  
  16. const observablePromise = (proc, timeoutPromise) => {
  17. let promise = null;
  18. return {
  19. obtain() {
  20. if (!promise) {
  21. promise = new Promise(resolve => {
  22. let mo = null;
  23. const f = () => {
  24. let t = proc();
  25. if (t) {
  26. mo.disconnect();
  27. mo.takeRecords();
  28. mo = null;
  29. resolve(t);
  30. }
  31. }
  32. mo = new MutationObserver(f);
  33. mo.observe(document, { subtree: true, childList: true })
  34. f();
  35. timeoutPromise && timeoutPromise.then(() => {
  36. resolve(null)
  37. });
  38. });
  39. }
  40. return promise
  41. }
  42. }
  43. }
  44.  
  45.  
  46. (async () => {
  47.  
  48.  
  49. const q = await observablePromise(() => {
  50.  
  51. try {
  52. return ytcfg.data_.WEB_PLAYER_CONTEXT_CONFIGS.WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH;
  53. } catch (e) { }
  54.  
  55.  
  56. }).obtain();
  57.  
  58.  
  59.  
  60. if (q) setup();
  61.  
  62. })();
  63.  
  64.  
  65.  
  66. let bb = false;
  67. const setup = () => {
  68. if (bb) return;
  69. bb = true;
  70.  
  71. const q = ytcfg.data_.WEB_PLAYER_CONTEXT_CONFIGS.WEB_PLAYER_CONTEXT_CONFIG_ID_KEVLAR_WATCH;
  72. if (q && q.serializedExperimentFlags) {
  73. const x = 85; // 17
  74. const y = 1.25; // 0.25
  75. q.serializedExperimentFlags = q.serializedExperimentFlags.replace(/&?html5_live_use_alternate_bandwidth_window_sizes=[^&=]*/, '') + '&html5_live_use_alternate_bandwidth_window_sizes=true'
  76. q.serializedExperimentFlags = q.serializedExperimentFlags.replace(/&?html5_live_ultra_low_latency_bandwidth_window=[^&=]*/, '') + '&html5_live_ultra_low_latency_bandwidth_window=' + x
  77. q.serializedExperimentFlags = q.serializedExperimentFlags.replace(/&?html5_live_low_latency_bandwidth_window=[^&=]*/, '') + '&html5_live_low_latency_bandwidth_window=' + x
  78. q.serializedExperimentFlags = q.serializedExperimentFlags.replace(/&?html5_live_normal_latency_bandwidth_window=[^&=]*/, '') + '&html5_live_normal_latency_bandwidth_window=' + x
  79. q.serializedExperimentFlags = q.serializedExperimentFlags.replace(/&?html5_min_startup_buffered_media_duration_for_live_secs=[^&=]*/, '') + '&html5_min_startup_buffered_media_duration_for_live_secs=' + y
  80. }
  81.  
  82. };
  83.  
  84. let cid1 = 0, cid2 = 0;
  85. let checks = new Set();
  86. let lastMedia = null;
  87. const onDelayDone = () => {
  88. const media = lastMedia;
  89. lastMedia = null;
  90. if (!media) return;
  91. // L = n * 1 - n * 0.968
  92. if (media.isConnected && media.playbackRate === 0.968) {
  93. media.playbackRate = 1;
  94. }
  95. }
  96. const delayCheck = () => {
  97. let media;
  98. for (const target of checks) {
  99. if (target.isConnected && target.playbackRate === 1 && target.matches('#player *, #ytd-player *')) {
  100. media = target;
  101. break;
  102. }
  103. }
  104. if (!media) return;
  105. if (!document.querySelector('.ytp-live-badge.ytp-live-badge-is-livehead')) return;
  106. if (cid2) clearTimeout(cid2);
  107. if (lastMedia && lastMedia.isConnected && lastMedia.playbackRate === 0.968) lastMedia.playbackRate = 1;
  108. lastMedia = media;
  109. media.playbackRate = 0.968;
  110. cid2 = setTimeout(onDelayDone, 30000);
  111. }
  112. document.addEventListener('canplay', (e) => {
  113. if (!e || !e.isTrusted || !(e.target instanceof HTMLMediaElement)) return;
  114. const p = document.querySelector('.ytp-live-badge.ytp-live-badge-is-livehead');
  115. const media = e.target;
  116. if (p && media.playbackRate === 1) {
  117. if (cid1) clearTimeout(cid1);
  118. checks.add(media);
  119. cid1 = setTimeout(delayCheck, 100);
  120. }
  121. }, true);
  122. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址