使用 YouTube AV1

使用 AV1 进行 YouTube 视频播放

当前为 2023-08-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Use YouTube AV1
  3. // @description Use AV1 for video playback on YouTube
  4. // @name:zh-TW 使用 YouTube AV1
  5. // @description:zh-TW 使用 AV1 進行 YouTube 影片播放
  6. // @name:zh-HK 使用 YouTube AV1
  7. // @description:zh-HK 使用 AV1 進行 YouTube 影片播放
  8. // @name:zh-CN 使用 YouTube AV1
  9. // @description:zh-CN 使用 AV1 进行 YouTube 视频播放
  10. // @name:ja YouTube AV1 の使用
  11. // @description:ja YouTube の動画再生に AV1 を使用する
  12. // @name:ko YouTube AV1 사용
  13. // @description:ko YouTube의 동영상 재생에 AV1을 사용하기
  14. // @name:vi Sử dụng YouTube AV1
  15. // @description:vi Sử dụng AV1 để phát video trên YouTube
  16. // @name:de YouTube AV1 verwenden
  17. // @description:de Verwende AV1 für die Videowiedergabe auf YouTube
  18. // @name:fr Utiliser YouTube AV1
  19. // @description:fr Utiliser AV1 pour la lecture des vidéos sur YouTube
  20. // @name:it Usa YouTube AV1
  21. // @description:it Usa AV1 per la riproduzione dei video su YouTube
  22. // @name:es Usar AV1 en YouTube
  23. // @description:es Usar AV1 para la reproducción de videos en YouTube
  24. // @namespace http://tampermonkey.net/
  25. // @version 2.0.1
  26. // @author CY Fung
  27. // @match https://www.youtube.com/*
  28. // @match https://www.youtube.com/embed/*
  29. // @match https://www.youtube-nocookie.com/embed/*
  30. // @exclude https://www.youtube.com/live_chat*
  31. // @exclude https://www.youtube.com/live_chat_replay*
  32. // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/
  33. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  34. // @grant none
  35. // @run-at document-start
  36. // @license MIT
  37. //
  38. // @compatible firefox Violentmonkey
  39. // @compatible firefox Tampermonkey
  40. // @compatible firefox FireMonkey
  41. // @compatible chrome Violentmonkey
  42. // @compatible chrome Tampermonkey
  43. // @compatible opera Violentmonkey
  44. // @compatible opera Tampermonkey
  45. // @compatible safari Stay
  46. // @compatible edge Violentmonkey
  47. // @compatible edge Tampermonkey
  48. // @compatible brave Violentmonkey
  49. // @compatible brave Tampermonkey
  50. //
  51. // @unwrap
  52. // @allFrames true
  53. // @inject-into page
  54. // ==/UserScript==
  55.  
  56. /**
  57. *
  58. * CAUTION:
  59. * This script will alter your site preference setting localStorage['yt-player-av1-pref'].
  60. * The modified setting will remain even if you have disabled or uninstalled the script.
  61. *
  62. */
  63.  
  64.  
  65. (function (__Promise__) {
  66. 'use strict';
  67.  
  68. /** @type {globalThis.PromiseConstructor} */
  69. const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  70.  
  71. console.debug("force-youtube-av1", "injected");
  72.  
  73. function enableAV1() {
  74.  
  75. console.debug("force-youtube-av1", "AV1 enabled");
  76.  
  77.  
  78. // This is the setting to force AV1
  79. // localStorage['yt-player-av1-pref'] = '8192';
  80. try{
  81. Object.defineProperty(localStorage, 'yt-player-av1-pref', { value: '8192', writable: true, enumerable: true, configurable: true });
  82. }catch(e){
  83. localStorage['yt-player-av1-pref'] = '8192';
  84. }
  85.  
  86. function typeTest(type) {
  87.  
  88.  
  89. let disallowed_types = ['vp8', 'vp9'];
  90. // mp4a is a container for AAC. In most cases (<192kbps), Opus is better than AAC.
  91. // vp09 will be also disabled if av1 is enabled.
  92. for (const disallowed_type of disallowed_types) {
  93. if (type.includes(disallowed_type)) return false;
  94. }
  95.  
  96. let force_allow_types = ['av1', 'av01', 'hev1'];
  97. // av1 is currently supported by Firefox and Chrome except Edge
  98. for (const force_allow_type of force_allow_types) {
  99. if (type.includes(force_allow_type)) return true;
  100. }
  101.  
  102. }
  103.  
  104. // return a custom MIME type checker that can defer to the original function
  105. function makeModifiedTypeChecker(origChecker) {
  106. // Check if a video type is allowed
  107. return function (type) {
  108. let res = undefined;
  109. if (type === undefined) res = false;
  110. else {
  111. res = typeTest(type);
  112. }
  113. if (res === undefined) res = origChecker.apply(this, arguments);
  114.  
  115. // console.debug(20, type, res)
  116.  
  117. return res;
  118. };
  119. }
  120.  
  121. // Override video element canPlayType() function
  122. const proto = (HTMLVideoElement || 0).prototype;
  123. if (proto && typeof proto.canPlayType == 'function') {
  124. proto.canPlayType = makeModifiedTypeChecker(proto.canPlayType);
  125. }
  126.  
  127. // Override media source extension isTypeSupported() function
  128. const mse = window.MediaSource;
  129. // Check for MSE support before use
  130. if (mse && typeof mse.isTypeSupported == 'function') {
  131. mse.isTypeSupported = makeModifiedTypeChecker(mse.isTypeSupported);
  132. }
  133.  
  134. }
  135.  
  136.  
  137. let promise = null;
  138.  
  139. function callback(result) {
  140.  
  141. if (result && result.supported && result.smooth) enableAV1();
  142. else {
  143. console.warn("force-youtube-av1", 'Your browser does not support AV1. You might conside to use the latest version of Google Chrome or Mozilla FireFox.');
  144.  
  145. }
  146. }
  147.  
  148.  
  149. try {
  150. promise = navigator.mediaCapabilities.decodingInfo({
  151. type: "file",
  152. video: {
  153. contentType: "video/mp4; codecs=av01.0.05M.08.0.110.05.01.06.0",
  154. height: 1080,
  155. width: 1920,
  156. framerate: 30,
  157. bitrate: 2826848,
  158. },
  159. audio: {
  160. contentType: "audio/webm; codecs=opus",
  161. channels: "2.1",
  162. samplerate: 44100,
  163. bitrate: 255236,
  164. }
  165. }).then(callback).catch(callback);
  166.  
  167. } catch (e) {
  168. promise = null;
  169. }
  170.  
  171. if (!promise) promise = Promise.resolve(0).then(callback).catch(callback);
  172.  
  173.  
  174.  
  175.  
  176. })(Promise);