视频和图片画质修复

强制播放最高画质的视频和图片

目前为 2024-09-11 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Video and Image Quality Fixer for All Sites
  3. // @name:zh 视频和图片画质修复
  4. // @name:zh-CN 视频和图片画质修复
  5. // @namespace https://github.com/yuhaofe
  6. // @version 0.4.1
  7. // @description Force highest quality playback for videos and images on all sites.
  8. // @description:zh 强制播放最高画质的视频和图片
  9. // @description:zh-CN 强制播放最高画质的视频和图片
  10. // @author tae
  11. // @match *://*/*
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17. initHijack();
  18. initUI();
  19. enhanceImages();
  20. function initHijack() {
  21. var realOpen = window.XMLHttpRequest.prototype.open;
  22. window.XMLHttpRequest.prototype.open = hijackedOpen;
  23. function hijackedOpen() {
  24. var url = arguments['1'];
  25. if (isHLSPlaylist(url)) {
  26. this.addEventListener('readystatechange', function(e) {
  27. if (this.readyState === 4) {
  28. var originalText = e.target.responseText;
  29. if(isMasterPlaylist(originalText)) {
  30. var modifiedText = modifyMasterPlaylist(originalText);
  31. Object.defineProperty(this, 'response', {writable: true});
  32. Object.defineProperty(this, 'responseText', {writable: true});
  33. this.response = this.responseText = modifiedText;
  34. }
  35. }
  36. });
  37. }
  38. return realOpen.apply(this, arguments);
  39. };
  40.  
  41. function isHLSPlaylist(url) {
  42. var reg = new RegExp(/.+m3u8?/, 'i');
  43. return reg.test(url);
  44. }
  45.  
  46. function isMasterPlaylist(text) {
  47. return text.indexOf('#EXT-X-TARGETDURATION') === -1 && text.indexOf('#EXT-X-STREAM-INF') != -1;
  48. }
  49.  
  50. function modifyMasterPlaylist(text) {
  51. var result = text;
  52. var reg = new RegExp(/^#EXT-X-STREAM-INF:.*BANDWIDTH=(\d+).*\r?\n.*$/, 'gm');
  53. var stream = reg.exec(text);
  54. if (stream) {
  55. var globalTags = text.substring(0, stream.index);
  56.  
  57. // find max bitrate media playlist
  58. var maxBitrateStream = stream;
  59. while((stream = reg.exec(text)) != null){
  60. if (parseInt(stream[1]) > parseInt(maxBitrateStream[1])) {
  61. maxBitrateStream = stream;
  62. }
  63. }
  64. result = globalTags + maxBitrateStream[0];
  65. }
  66. return result;
  67. }
  68. }
  69. function initUI() {
  70. // add a mark helps identify if userscript loaded successfully
  71. var disableHQ = localStorage.getItem('vqfft-disablehq');
  72. if(!disableHQ) {
  73. var mark = document.createElement('button');
  74. mark.innerText = 'HQ';
  75. mark.style = "position: fixed; right: 5px; top: 5px; color: white; border-width: 0px; border-radius: 5px; background-color: silver; opacity: 0.8; z-index: 1000;";
  76. mark.onclick = function() {
  77. if(confirm('Do not display HQ mark anymore?')){
  78. localStorage.setItem('vqfft-disablehq', 'true');
  79. mark.remove();
  80. } else {
  81. toggleFeatures();
  82. }
  83. };
  84. document.body.appendChild(mark);
  85. }
  86. }
  87.  
  88. function toggleFeatures() {
  89. var disableHQ = localStorage.getItem('vqfft-disablehq');
  90. if(disableHQ) {
  91. localStorage.removeItem('vqfft-disablehq');
  92. alert('High Quality features enabled.');
  93. } else {
  94. localStorage.setItem('vqfft-disablehq', 'true');
  95. alert('High Quality features disabled.');
  96. }
  97. }
  98.  
  99. function enhanceImages() {
  100. window.addEventListener('load', function() {
  101. var images = document.querySelectorAll('img:not([src*="ad"])');
  102. images.forEach(function(img) {
  103. var src = img.src;
  104. if (src) {
  105. img.src = src.replace(/(\?.*)|(#.*)/, '') + '?quality=100';
  106. }
  107. });
  108. });
  109. }
  110. })();

QingJ © 2025

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