自动切换抖音到最高可用画质(4K>2K>1080P>720P),支持自定义检测时间间隔
// ==UserScript==
// @name 抖音自动切换最高画质
// @namespace http://tampermonkey.net/
// @version 1.2
// @description 自动切换抖音到最高可用画质(4K>2K>1080P>720P),支持自定义检测时间间隔
// @author zpc5560
// @match *://*.douyin.com/*
// @grant none
// @icon http://www.missyuan.net/uploads/allimg/190118/11341Q918-11.jpg
// ==/UserScript==
(function() {
'use strict';
let isQualitySwitched = false;
let currentQuality = null;
let lastAttemptTime = 0;
let currentVideoSrc = null;
let currentTransformValue = 'translate3d(0px, 0px, 0px)';
const DEFAULT_CHECK_INTERVAL = 5 * 60 * 1000; // 默认5分钟
const MAX_CHECK_INTERVAL = 60 * 60 * 1000; // 最大1小时
let CHECK_INTERVAL = DEFAULT_CHECK_INTERVAL;
let checkTimer = null;
// 定义画质优先级
const qualityPriority = [
{ name: '超清 4K', minHeight: 2160 },
{ name: '超清 2K', minHeight: 1440 },
{ name: '高清 1080P', minHeight: 1080 },
{ name: '高清 720P', minHeight: 720 }
];
// 创建设置按钮
function createSettingsButton() {
const button = document.createElement('button');
button.textContent = '设置检测间隔';
button.style.cssText = `
position: fixed;
bottom: 90px;
left: 20px;
z-index: 999999;
padding: 8px 12px;
background-color: rgba(34, 34, 34, 0.9);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
`;
button.addEventListener('click', showSettingsDialog);
document.body.appendChild(button);
}
// 显示设置对话框
function showSettingsDialog() {
const dialog = document.createElement('div');
dialog.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
z-index: 10000;
min-width: 300px;
`;
const currentInterval = CHECK_INTERVAL / 1000;
const minutes = Math.floor(currentInterval / 60);
const seconds = currentInterval % 60;
dialog.innerHTML = `
<h3 style="margin: 0 0 15px 0; color: #333;">设置检测间隔</h3>
<div style="margin-bottom: 15px;">
<label style="display: inline-block; width: 50px; color: #666;">分钟:</label>
<input type="number" id="minutes" value="${minutes}" min="0" max="60" style="width: 60px; padding: 4px;">
</div>
<div style="margin-bottom: 15px;">
<label style="display: inline-block; width: 50px; color: #666;">秒钟:</label>
<input type="number" id="seconds" value="${seconds}" min="0" max="59" style="width: 60px; padding: 4px;">
</div>
<div style="color: #666; font-size: 12px; margin-bottom: 15px;">
注意:总时间不能超过1小时
</div>
<div style="text-align: right;">
<button id="cancelBtn" style="margin-right: 10px; padding: 6px 12px; background: #f5f5f5; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;">取消</button>
<button id="saveBtn" style="padding: 6px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer;">保存</button>
</div>
`;
document.body.appendChild(dialog);
const minutesInput = dialog.querySelector('#minutes');
const secondsInput = dialog.querySelector('#seconds');
const saveBtn = dialog.querySelector('#saveBtn');
const cancelBtn = dialog.querySelector('#cancelBtn');
// 保存设置
saveBtn.addEventListener('click', () => {
const minutes = parseInt(minutesInput.value) || 0;
const seconds = parseInt(secondsInput.value) || 0;
const totalSeconds = minutes * 60 + seconds;
if (totalSeconds === 0) {
alert('检测间隔不能为0');
return;
}
if (totalSeconds > 3600) {
alert('检测间隔不能超过1小时');
return;
}
CHECK_INTERVAL = totalSeconds * 1000;
localStorage.setItem('douyinQualityCheckInterval', CHECK_INTERVAL.toString());
resetState();
document.body.removeChild(dialog);
});
// 取消设置
cancelBtn.addEventListener('click', () => {
document.body.removeChild(dialog);
});
}
// 获取当前选中的画质
function getCurrentQuality() {
const selectedItem = document.querySelector('.virtual .item.selected');
return selectedItem ? selectedItem.textContent.trim() : null;
}
// 移除悬停效果
function removeHoverEffect() {
const mouseOutEvent = new MouseEvent('mouseout', {
bubbles: true,
cancelable: true,
view: window
});
const qualityButton = document.querySelector('.gear.isSmoothSwitchClarityLogin');
if (qualityButton) {
qualityButton.dispatchEvent(mouseOutEvent);
}
}
// 检查画质是否需要切换
function checkQualityNeedsSwitch() {
const currentSelectedQuality = getCurrentQuality();
const currentTime = Date.now();
if (!currentQuality ||
currentSelectedQuality !== currentQuality ||
currentTime - lastAttemptTime >= CHECK_INTERVAL) {
isQualitySwitched = false;
switchToHighQuality();
}
}
// 检查视频源是否更改
function checkVideoSourceChanged() {
const videoElement = document.querySelector('video');
const transformElement = document.querySelector('.kkbhJDRa.MvotIm_G');
if (videoElement && transformElement) {
const newVideoSrc = videoElement.src;
const newTransformValue = transformElement.style.transform;
if (newVideoSrc !== currentVideoSrc || newTransformValue !== currentTransformValue) {
currentVideoSrc = newVideoSrc;
currentTransformValue = newTransformValue;
isQualitySwitched = false;
switchToHighQuality();
}
}
}
function switchToHighQuality() {
if (isQualitySwitched) return;
const qualityButton = document.querySelector('.gear.isSmoothSwitchClarityLogin');
if (qualityButton) {
const mouseOverEvent = new MouseEvent('mouseover', {
bubbles: true,
cancelable: true,
view: window
});
qualityButton.dispatchEvent(mouseOverEvent);
setTimeout(() => {
const qualityOptions = Array.from(document.querySelectorAll('.virtual .item'));
let selectedOption = null;
for (const quality of qualityPriority) {
const option = qualityOptions.find(opt =>
opt.textContent.includes(quality.name)
);
if (option) {
selectedOption = option;
break;
}
}
if (selectedOption) {
selectedOption.click();
currentQuality = selectedOption.textContent.trim();
lastAttemptTime = Date.now();
console.log(`已切换到${currentQuality}画质`);
isQualitySwitched = true;
startQualityCheck();
} else {
const smartOption = qualityOptions.find(opt =>
opt.textContent.includes('智能')
);
if (smartOption) {
smartOption.click();
currentQuality = '智能';
lastAttemptTime = Date.now();
console.log('未找到720P或更高画质,暂时切换到智能画质');
isQualitySwitched = true;
startQualityCheck();
}
}
setTimeout(removeHoverEffect, 100);
}, 500);
} else {
console.log('画质选择按钮未找到');
}
}
// 启动定时检测
function startQualityCheck() {
if (checkTimer) {
clearInterval(checkTimer);
}
checkTimer = setInterval(() => {
console.log('定时检测视频源中...');
checkVideoSourceChanged();
}, CHECK_INTERVAL);
}
// 停止定时检测
function stopQualityCheck() {
if (checkTimer) {
clearInterval(checkTimer);
checkTimer = null;
}
}
// 使用 MutationObserver 监听页面变化
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
if (mutation.type === 'childList' || mutation.type === 'attributes') {
const videoElement = document.querySelector('video');
const transformElement = document.querySelector('.kkbhJDRa.MvotIm_G');
if (videoElement && transformElement && !isQualitySwitched) {
checkVideoSourceChanged();
}
}
});
});
observer.observe(document.body, { childList: true, subtree: true, attributes: true });
// 在页面切换时重置状态
function resetState() {
isQualitySwitched = false;
currentQuality = null;
lastAttemptTime = 0;
currentVideoSrc = null;
currentTransformValue = 'translate3d(0px, 0px, 0px)';
stopQualityCheck();
startQualityCheck();
}
// 初始化检测间隔
function initCheckInterval() {
const savedInterval = localStorage.getItem('douyinQualityCheckInterval');
if (savedInterval) {
const interval = parseInt(savedInterval);
if (!isNaN(interval) && interval > 0 && interval <= MAX_CHECK_INTERVAL) {
CHECK_INTERVAL = interval;
}
}
}
window.addEventListener('urlchange', resetState);
window.addEventListener('load', () => {
initCheckInterval();
createSettingsButton();
resetState();
switchToHighQuality();
});
window.addEventListener('unload', () => {
stopQualityCheck();
});
// 初始启动
setTimeout(() => {
initCheckInterval();
createSettingsButton();
resetState();
}, 1000);
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址