Greasy Fork is available in English.
V6.1美化版:右上方胶囊开关。优先检测并自动跳过直播,非直播视频自动强制切换到最高画质 (4K/2K/1080P)。
// ==UserScript==
// @name 抖音优化: 强制最高画质+自动跳过直播
// @namespace http://tampermonkey.net/
// @version 6.1
// @description V6.1美化版:右上方胶囊开关。优先检测并自动跳过直播,非直播视频自动强制切换到最高画质 (4K/2K/1080P)。
// @author You
// @match https://www.douyin.com/*
// @match https://live.douyin.com/*
// @grant none
// @run-at document-idle
// @license All Rights Reserved
// ==/UserScript==
(function() {
'use strict';
// ==========================================
// 全局配置参数
// ==========================================
const MAIN_INTERVAL = 1000; // 主循环检测频率 (毫秒)
const SKIP_COOLDOWN = 1500; // 跳过直播后的冷却时间
const QUALITIES = ["超清 4K", "超清 2K", "高清 1080P"]; // 画质优先级
// ==========================================
// 全局状态变量
// ==========================================
let isSkipping = false;
// 读取开关状态,默认开启
let isSkipEnabled = localStorage.getItem('dy_skip_live_enabled') !== 'false';
let lastVideoSrc = "";
let isQualityChecked = false;
// ==========================================
// 工具函数库
// ==========================================
// 1. 模拟按键
function simulateKeyDown() {
const event = new KeyboardEvent('keydown', {
key: 'ArrowDown', code: 'ArrowDown', keyCode: 40, which: 40,
bubbles: true, cancelable: true
});
document.dispatchEvent(event);
console.log('【抖音助手】执行跳过');
}
// 2. 元素可视检测
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
const windowHeight = (window.innerHeight || document.documentElement.clientHeight);
const windowWidth = (window.innerWidth || document.documentElement.clientWidth);
return (rect.top >= 0 && rect.bottom <= windowHeight) && (rect.left < windowWidth * 0.75);
}
// 3. 提示 Toast
function showToast(text) {
const existing = document.getElementById('dy-helper-toast');
if(existing) existing.remove();
const div = document.createElement('div');
div.id = 'dy-helper-toast';
div.innerText = text;
div.style.cssText = `
position: fixed; top: 20%; left: 50%; transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.85); color: #fff; padding: 12px 24px;
border-radius: 50px; z-index: 100000; font-size: 15px; pointer-events: none;
box-shadow: 0 5px 15px rgba(0,0,0,0.4); transition: opacity 0.3s; font-weight: bold;
backdrop-filter: blur(5px);
`;
document.body.appendChild(div);
setTimeout(() => { div.style.opacity = '0'; setTimeout(() => div.remove(), 500); }, 1500);
}
// 4. 指针事件
function triggerPointerEvent(element, eventType) {
if (!element) return;
element.dispatchEvent(new PointerEvent(eventType, {
bubbles: true, cancelable: true, view: window,
pointerId: 1, width: 1, height: 1, isPrimary: true, pointerType: 'mouse'
}));
}
// 5. 查找画质按钮
function findResolutionButton() {
const keywords = ["智能", "标清", "高清", "超清", "4K", "1080P", "720P"];
const tags = ['span', 'div'];
for (let tag of tags) {
const els = document.getElementsByTagName(tag);
for (let i = els.length - 1; i >= 0; i--) {
const el = els[i];
if (!el.innerText) continue;
const txt = el.innerText.trim();
if (keywords.some(k => txt.includes(k))) {
if (el.clientHeight > 10 && el.clientHeight < 50 && el.clientWidth < 150) {
return el;
}
}
}
}
return null;
}
// ==========================================
// UI 界面模块 (美化版)
// ==========================================
function initUI() {
// 主容器
const btn = document.createElement('div');
// 样式:右上方,胶囊形状,鲜艳配色
const updateStyle = () => {
const bgColor = isSkipEnabled ? 'linear-gradient(135deg, #00C853, #69F0AE)' : '#333'; // 开启绿色渐变,关闭深灰
const textColor = isSkipEnabled ? '#004D40' : '#888';
const icon = isSkipEnabled ? '⚡' : '🚫';
const shadow = isSkipEnabled ? '0 0 15px rgba(0, 230, 118, 0.6)' : 'none';
btn.style.background = bgColor;
btn.style.boxShadow = shadow;
btn.innerHTML = `
<span style="font-size: 18px; margin-right: 6px;">${icon}</span>
<span style="font-weight: 800; color: ${isSkipEnabled?'#fff':'#aaa'}; font-family: system-ui;">跳过直播</span>
<div style="margin-left: 8px; width: 34px; height: 20px; background: rgba(255,255,255,0.3); border-radius: 10px; position: relative;">
<div style="
width: 16px; height: 16px; background: #fff; border-radius: 50%;
position: absolute; top: 2px; left: ${isSkipEnabled ? '16px' : '2px'};
transition: left 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2);
"></div>
</div>
`;
};
btn.style.cssText = `
position: fixed; top: 100px; right: 30px; z-index: 999999;
display: flex; align-items: center; justify-content: center;
padding: 8px 16px; border-radius: 50px; cursor: pointer;
opacity: 0.6; transition: all 0.3s ease; transform: scale(1);
user-select: none; border: 2px solid rgba(255,255,255,0.1);
height: 44px; box-sizing: border-box;
`;
// 交互效果
btn.onmouseenter = () => {
btn.style.opacity = '1';
btn.style.transform = 'scale(1.05)';
};
btn.onmouseleave = () => {
btn.style.opacity = '0.6';
btn.style.transform = 'scale(1)';
};
// 点击事件
btn.addEventListener('click', () => {
isSkipEnabled = !isSkipEnabled;
localStorage.setItem('dy_skip_live_enabled', isSkipEnabled);
updateStyle();
showToast(`自动跳过直播已${isSkipEnabled ? '开启 ⚡' : '关闭 🚫'}`);
});
// 初始化
updateStyle();
document.body.appendChild(btn);
}
// ==========================================
// 核心模块 A: 直播检测
// ==========================================
function checkLiveStream() {
if (!isSkipEnabled) return false; // 开关关闭则不检测
if (isSkipping) return true;
const xpath = "//*[text()='直播中']";
const result = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0; i < result.snapshotLength; i++) {
let element = result.snapshotItem(i);
if (isElementInViewport(element)) {
if (element.offsetParent === null) continue;
showToast("⚡ 检测到直播,跳过...");
isSkipping = true;
simulateKeyDown();
setTimeout(() => { isSkipping = false; }, SKIP_COOLDOWN);
return true;
}
}
return false;
}
// ==========================================
// 核心模块 B: 画质调节
// ==========================================
function checkVideoQuality() {
const video = document.querySelector('video');
if (!video) return;
if (video.src !== lastVideoSrc) {
lastVideoSrc = video.src;
isQualityChecked = false;
}
if (isQualityChecked) return;
const triggerBtn = findResolutionButton();
if (!triggerBtn) return;
const currentText = triggerBtn.innerText;
if (currentText.includes("4K")) {
isQualityChecked = true;
return;
}
triggerPointerEvent(triggerBtn, 'pointerover');
triggerPointerEvent(triggerBtn, 'pointerenter');
setTimeout(() => {
let foundTarget = false;
for (let q of QUALITIES) {
if (currentText.includes(q)) {
foundTarget = true;
break;
}
const allDivs = document.querySelectorAll('div, span, p');
for (let node of allDivs) {
if (node.innerText === q && node !== triggerBtn) {
// console.log(`[画质] 切换: ${q}`);
triggerPointerEvent(node, 'pointerdown');
triggerPointerEvent(node, 'mousedown');
triggerPointerEvent(node, 'pointerup');
triggerPointerEvent(node, 'mouseup');
node.click();
foundTarget = true;
triggerPointerEvent(triggerBtn, 'pointerout');
triggerPointerEvent(triggerBtn, 'pointerleave');
const player = document.querySelector('.xgplayer-container') || document.body;
triggerPointerEvent(player, 'pointermove');
break;
}
}
if (foundTarget) break;
}
if (foundTarget || !currentText.includes("智能")) {
isQualityChecked = true;
triggerPointerEvent(triggerBtn, 'pointerleave');
}
}, 300);
}
// ==========================================
// 主运行
// ==========================================
initUI();
console.log('【抖音助手】V6.1 启动');
setInterval(() => {
if (!checkLiveStream()) {
checkVideoQuality();
}
}, MAIN_INTERVAL);
})();