
// ==UserScript==
// @name YouTube 自动选择最高画质 & 网速换算
// @namespace https://greasyfork.org/zh-CN/scripts/544945-youtube-自动选择最高画质-自动跳过广告
// @version 4.2
// @description 自动将 YouTube 视频设置为最高可用画质,并将详细统计信息中的 Connection Speed (Kbps) 换算为 MB/s。稳定、高效、省心。
// @author blues max (融合优化)
// @match https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// --- 全局配置区 ---
const CONFIG = {
// 画质相关配置
setQuality: true, // 是否启用自动画质选择功能
preferredQualities: ['highres', 'hd2160', 'hd1440', 'hd1080', 'hd720'], // 优先画质列表
// 统计信息网速换算配置
convertSpeed: true, // 是否将 Connection Speed (Kbps) 换算为 MB/s
// 调试模式
debug: false // 设置为 true 可在控制台看到详细日志
};
const log = (...args) => {
if (CONFIG.debug) {
console.log('[YT-Ultimate]', ...args);
}
};
// --- 模块一:画质选择 ---
/**
* 设置画质的核心函数
* @param {object} player - YouTube 播放器实例
* @returns {boolean} - 是否成功设置或检查完毕
*/
function setBestQuality(player) {
if (!player || typeof player.getAvailableQualityLevels !== 'function') {
log('画质模块: 播放器或 API 不可用。');
return false;
}
const availableQualities = player.getAvailableQualityLevels();
if (availableQualities.length === 0) {
log('画质模块: 画质列表为空,等待下一次机会。');
return false;
}
log('画质模块: 可用画质:', availableQualities);
for (const quality of CONFIG.preferredQualities) {
if (availableQualities.includes(quality)) {
const currentQuality = player.getPlaybackQuality();
if (currentQuality !== quality) {
player.setPlaybackQualityRange(quality);
player.setPlaybackQuality(quality);
log(`✅ 画质已成功切换到 -> ${quality}`);
} else {
log(`👍 当前画质 (${currentQuality}) 已是最佳,无需更改。`);
}
return true;
}
}
log('🤷♂️ 未找到偏好的画质选项。');
return true;
}
/**
* 轮询检查播放器是否准备就绪并设置画质
*/
function pollingCheckQuality() {
let attempts = 0;
const maxAttempts = 15;
const intervalId = setInterval(() => {
const player = document.getElementById('movie_player');
attempts++;
if (player && typeof player.getAvailableQualityLevels === 'function') {
if (setBestQuality(player)) {
clearInterval(intervalId);
attachStateChangeListener(player);
}
}
if (attempts >= maxAttempts) {
log('画质模块: 超时,未能找到播放器或设置画质。');
clearInterval(intervalId);
}
}, 1000);
}
/**
* 附加 onStateChange 监听器,用于在视频变化后快速恢复画质
*/
function attachStateChangeListener(player) {
if (player.dataset.qualityListenerAttached === 'true') return;
player.addEventListener('onStateChange', (state) => {
if (state === 1) { // 1 = 正在播放
log('▶️ 播放状态改变,重新检查画质...');
setTimeout(() => setBestQuality(player), 250);
}
});
player.dataset.qualityListenerAttached = 'true';
log('画质模块: 事件监听器已附加。');
}
// --- 模块二:详细统计信息网速换算 ---
/**
* 将面板中的 Connection Speed (Kbps) 换算为 MB/s
* @param {Element} panel - 统计信息面板 DOM 元素
*/
function convertStatsSpeed(panel) {
const walker = document.createTreeWalker(panel, NodeFilter.SHOW_TEXT, null, false);
let node;
while ((node = walker.nextNode())) {
if (/\b\d[\d\s,]*\s*Kbps\b/i.test(node.nodeValue)) {
node.nodeValue = node.nodeValue.replace(/(\d[\d\s,]*)\s*Kbps/gi, (match, p1) => {
const kbps = parseFloat(p1.replace(/[, \s]/g, ''));
if (isNaN(kbps)) return match;
// 换算公式: 1 MB/s = 8000 Kbps (标准 Megabytes/s)
const mbps = (kbps / 8000).toFixed(2);
return `${mbps} MB/s`;
});
}
}
}
/**
* 监听并捕获详细统计面板
*/
function initStatsObserver() {
if (!CONFIG.convertSpeed) return;
const observer = new MutationObserver(() => {
const panel = document.querySelector('.html5-video-info-panel');
if (panel) {
convertStatsSpeed(panel);
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
characterData: true
});
log('网速单位换算模块已启动。');
}
// --- 脚本主入口 ---
log('YouTube 脚本启动!');
// 启动画质选择功能
if (CONFIG.setQuality) {
log('画质选择功能已启用。');
window.addEventListener('yt-navigate-finish', () => {
log('--- 页面导航完成,启动画质检查 ---');
pollingCheckQuality();
});
pollingCheckQuality(); // 首次加载时执行
}
// 启动统计信息网速换算功能
initStatsObserver();
})();