YouTube 固定分辨率 + 编码智能选择

YouTube 播放时固定分辨率为 1440p 60hz,CPU 占用率过高时自动更换编码(av1,vp09)

目前为 2025-01-08 提交的版本。查看 最新版本

// ==UserScript==
// @name         YouTube 固定分辨率 + 编码智能选择
// @namespace    https://gf.qytechs.cn/users/1171320
// @version      1.01
// @description  YouTube 播放时固定分辨率为 1440p 60hz,CPU 占用率过高时自动更换编码(av1,vp09)
// @author       Lama AI 辅助
// @match        *://www.youtube.com/watch?v=*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

     let cpuUsageHistory = []; // 存储 CPU 使用率历史
     let highCpuCount = 0; // 记录 CPU 占用率持续高于阈值的次数
    let lastChangeTime = 0; // 记录上次切换编码的时间
    const cpuCheckInterval = 1500; // CPU 监控间隔(ms)
    const cpuThreshold = 50; // CPU 占用率阈值(%)
    const changeInterval = 15000; // 切换编码最小间隔(ms)
    const highCpuDuration = 3; // cpu 高占用持续时长(s)
    let videoPlayer = null;
    let currentCodec = null;
    let preferredCodec = null;
   const preferredResolution = '1440p60';  // 设置期望的分辨率
    const codecOptions = ['avc1', 'vp9']; // 可选的编码
   let observer;

  // MutationObserver 监听器,用于检测视频元素
   const initObserver = () => {
      observer = new MutationObserver(mutations => {
          for (const mutation of mutations) {
              if (mutation.addedNodes) {
                  for (const node of mutation.addedNodes) {
                      if (node.tagName === 'VIDEO') {
                        videoPlayer = node;
                        // 设置初始分辨率
                         setResolution();
                          // 开始监控 CPU
                        startCpuMonitor();
                        return;
                    }
                  }
              }
          }
      });

          observer.observe(document.body, {
            childList: true,
              subtree: true
          });
      };
        initObserver();

   // 设置分辨率
    function setResolution(retryCount = 0) {
           if (!videoPlayer) return;

        const qualityMenuBtn = document.querySelector('button.ytp-button.ytp-settings-button');
       if(qualityMenuBtn){
           qualityMenuBtn.click();
            setTimeout(() => {
                 const qualityOption = Array.from(document.querySelectorAll('div.ytp-menu div.ytp-menu div.ytp-menu-label')).find(el => el.textContent.trim() === preferredResolution);
                  if(qualityOption) {
                        qualityOption.click();
                     } else {
                           const autoOption = Array.from(document.querySelectorAll('div.ytp-menu div.ytp-menu div.ytp-menu-label')).find(el => el.textContent.trim() === '自动');
                           if(autoOption) {
                                autoOption.click();
                            }
                       }
                 }, 500);
        }else {
              if (retryCount < 3) {
                 setTimeout(() => setResolution(retryCount + 1), 1000);  // 尝试重试,最多三次
           } else {
                console.warn('Failed to set resolution after multiple retries');
           }
       }
    }


      function startCpuMonitor(){
          if (!videoPlayer) return;
          checkInitialCodec()
          setInterval(checkCpu, cpuCheckInterval);
      }

    // 检测初始视频编码
      function checkInitialCodec() {
          if (!videoPlayer) return;
           const playerConfig = unsafeWindow.ytplayer?.config;
           if(playerConfig?.args?.player_response) {
                const codecs = playerConfig.args.player_response.streamingData?.adaptiveFormats.map(format => format.mimeType.match(/codecs="([^"]+)"/)?.[1]).filter(Boolean) || [];
               currentCodec = codecs.find(codec => codecOptions.includes(codec)) || null;
               preferredCodec = currentCodec;
           }
      }

   function checkCpu() {
         getCpuUsage()
             .then(usage => {
                 cpuUsageHistory.push(usage);
                 if (cpuUsageHistory.length > 10) {
                     cpuUsageHistory.shift();
                 }
                if(usage > cpuThreshold){
                      highCpuCount++;
                  }else{
                       highCpuCount = 0;
                   }
                  if (highCpuCount >= (highCpuDuration*1000/cpuCheckInterval) && (Date.now() - lastChangeTime) > changeInterval) {
                      console.log('CPU占用率过高,更换编码');
                       changeVideoCodec();
                        lastChangeTime = Date.now();
                      highCpuCount = 0;
                 }
           });
     }
   // 获取 CPU 占用率(兼容不同浏览器)
     async function getCpuUsage() {
       if (performance && performance.memory) { // chrome
           return 100 * (performance.memory.usedJSHeapSize / performance.memory.jsHeapSizeLimit);
        }else if(navigator.deviceMemory){  // firebox
            // 使用内存占用率估算
            return 100 - (navigator.deviceMemory /8) * 100;
       }
        else {
           return Promise.resolve(0); // 如果没有性能 API,则返回 0
       }
    }

  // 切换视频编码
    function changeVideoCodec() {
      if (!videoPlayer) return;
      const playerConfig = unsafeWindow.ytplayer?.config;
       if(playerConfig?.args?.player_response){
            const codecs = playerConfig.args.player_response.streamingData?.adaptiveFormats.map(format => format.mimeType.match(/codecs="([^"]+)"/)?.[1]).filter(Boolean) || [];
             const availableCodecs = codecs.filter(codec => codecOptions.includes(codec))
            const currentCodecIndex =  availableCodecs.indexOf(currentCodec)
           const nextCodecIndex = (currentCodecIndex + 1) % availableCodecs.length;
           const nextCodec = availableCodecs[nextCodecIndex];
          if(nextCodec) {
                currentCodec = nextCodec;
                videoPlayer.pause();
               console.log(`切换到 ${currentCodec} 编码`)
                videoPlayer.play();
               // 切换编码后,设置播放器重新加载
                videoPlayer.src = playerConfig.args.url
              } else {
               console.warn("未找到可用编码进行切换")
          }
       }
   }
   // 添加按钮事件监听
   function addCodecButton() {
        const actions = document.querySelector(".ytp-right-controls")
         if (actions) {
              const button = document.createElement('button');
           button.classList.add('ytp-button');
             button.textContent = "重置编码";
             button.style.marginLeft = "10px"
               button.onclick = () => {
                console.log(`切换到原始编码${preferredCodec}`)
                 currentCodec = preferredCodec;
                   changeVideoCodec()
              }
            actions.appendChild(button);
          }
      }
     addCodecButton()
    // 当页面DOM加载完成时执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initObserver);
    } else {
      initObserver()
    }
})();

QingJ © 2025

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