YouTube enhancer for Via

NewPipe button, force H.264 ≤30FPS, persistent quality lock, HW acceleration and opening videos and shorts in new tab so that pressing back gets you to previous tab without reloading.

  1. // ==UserScript==
  2. // @name YouTube enhancer for Via
  3. // @namespace https://viayoo.com/
  4. // @version 1.3
  5. // @license MIT
  6. // @description NewPipe button, force H.264 ≤30FPS, persistent quality lock, HW acceleration and opening videos and shorts in new tab so that pressing back gets you to previous tab without reloading.
  7. // @author jc
  8. // @match *://*.youtube.com/*
  9. // @match *://*.youtube-nocookie.com/*
  10. // @match *://*.youtubekids.com/*
  11. // @match https://m.youtube.com/*
  12. // @exclude *://www.youtube.com/*/music*
  13. // @exclude *://music.youtube.com/*
  14. // @run-at document-start
  15. // @grant none
  16. // ==/UserScript==
  17.  
  18. (function() {
  19. 'use strict';
  20.  
  21. // 1. FORCE H.264 & ≤30 FPS EVERYWHERE
  22. (function(){
  23. const BAD = /webm|vp8|vp9|av01/i;
  24. const FR = /framerate=(\d+)/;
  25. const ms = window.MediaSource;
  26. if (!ms) return;
  27. const orig = ms.isTypeSupported.bind(ms);
  28. ms.isTypeSupported = type => {
  29. if (typeof type !== 'string' || BAD.test(type)) return false;
  30. const m = FR.exec(type);
  31. if (m && +m[1] > 30) return false;
  32. return orig(type);
  33. };
  34. })();
  35.  
  36. // 2. GPU-KICK HACK: hidden 1×1 WebGL canvas (offscreen/no styling touch)
  37. (function(){
  38. try {
  39. const c = document.createElement('canvas');
  40. c.width = 1;
  41. c.height = 1;
  42. // use OffscreenCanvas if available
  43. const ctx = (window.OffscreenCanvas
  44. ? new OffscreenCanvas(1,1).getContext('webgl')
  45. : c.getContext('webgl'));
  46. // we never add it to the DOM, but context init triggers GPU paths
  47. } catch (e) {
  48. // ignore
  49. }
  50. })();
  51.  
  52. // 3. YOUTUBE-ONLY: NewPipe download button
  53. if (/^https?:\/\/(?:\w+\.)?youtube\.com/.test(location.href)) {
  54. (function addNewPipeBtn(){
  55. function makeBtn(){
  56. const btn = document.createElement('div');
  57. btn.textContent = '↓';
  58. Object.assign(btn.style, {
  59. position: 'fixed',
  60. bottom: '80px',
  61. right: '16px',
  62. width: '44px',
  63. height: '44px',
  64. display: 'flex',
  65. alignItems: 'center',
  66. justifyContent: 'center',
  67. fontSize: '24px',
  68. background: '#222',
  69. color: '#fff',
  70. borderRadius: '50%',
  71. boxShadow: '0 2px 10px rgba(0,0,0,0.3)',
  72. cursor: 'pointer',
  73. zIndex: 999999,
  74. opacity: '0.6',
  75. transition: 'opacity .2s, transform .2s'
  76. });
  77. btn.addEventListener('mouseenter', ()=> btn.style.opacity='1');
  78. btn.addEventListener('mouseleave', ()=> btn.style.opacity='0.6');
  79. btn.addEventListener('click', ()=>{
  80. let id = new URL(location.href).searchParams.get('v');
  81. if (!id) {
  82. const m = location.pathname.match(/\/shorts\/([^\/?&]+)/);
  83. id = m && m[1];
  84. }
  85. if (id) {
  86. location.href = `intent://www.youtube.com/watch?v=${id}#Intent;scheme=https;package=org.schabi.newpipe;end`;
  87. }
  88. });
  89. document.body.appendChild(btn);
  90. }
  91. if (document.body) makeBtn();
  92. else new MutationObserver((_, obs)=>{
  93. if (document.body) {
  94. obs.disconnect();
  95. makeBtn();
  96. }
  97. }).observe(document.documentElement,{childList:true});
  98. })();
  99.  
  100. // 4. YOUTUBE-ONLY: Persistent quality locker
  101. (function(){
  102. const KEY = 'yt_quality_preference';
  103. // watch menu for clicks on “240p, 360p, …”
  104. new MutationObserver(()=>{
  105. document.querySelectorAll('.ytp-menuitem-label')
  106. .forEach(el=>{
  107. if (/^\d+p$/.test(el.textContent)) {
  108. el.addEventListener('click',()=>{
  109. localStorage.setItem(KEY, el.textContent);
  110. },{once:true});
  111. }
  112. });
  113. }).observe(document.documentElement,{childList:true,subtree:true});
  114.  
  115. const apply = ()=>{
  116. const q = localStorage.getItem(KEY);
  117. if (!q) return;
  118. const setQ = ()=>{
  119. const vid = document.querySelector('video');
  120. const player =
  121. vid?.player_ ||
  122. window.ytplayer?.config?.args ||
  123. (window.yt && yt.player && yt.player.getPlayerByElement &&
  124. yt.player.getPlayerByElement(document.querySelector('#movie_player')));
  125. try {
  126. player?.setPlaybackQuality(q);
  127. player?.setPlaybackQualityRange?.(q);
  128. } catch(e){}
  129. };
  130. const t = setInterval(setQ, 1000);
  131. setTimeout(()=> clearInterval(t), 8000);
  132. };
  133. document.addEventListener('yt-navigate-finish', apply);
  134. window.addEventListener('load', apply);
  135. })();
  136.  
  137. // 5. YOUTUBE-ONLY MOBILE: open video links in new tab
  138. if (/^https?:\/\/m\.youtube\.com/.test(location.href)) {
  139. document.body.addEventListener('click', e=>{
  140. const a = e.target.closest('a[href]');
  141. if (!a) return;
  142. const u = a.href;
  143. if ((u.includes('/watch?v=') || u.includes('/shorts/'))
  144. && !a.closest('ytm-pivot-bar-renderer')
  145. && !a.closest('ytm-player-controls-overlay-renderer')
  146. && !a.closest('.player-controls-middle')) {
  147. e.preventDefault();
  148. e.stopPropagation();
  149. window.open(u, '_blank');
  150. }
  151. }, true);
  152. }
  153. }
  154. })();

QingJ © 2025

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