Greasy Fork

来自缓存

Greasy Fork is available in English.

抖音优化: 强制最高画质+自动跳过直播

V6更新:二合一版。优先检测并自动跳过直播(精准防误判),非直播视频自动强制切换到最高画质 (4K/2K/1080P)。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         抖音优化: 强制最高画质+自动跳过直播
// @namespace    http://tampermonkey.net/
// @version      6.0
// @description  V6更新:二合一版。优先检测并自动跳过直播(精准防误判),非直播视频自动强制切换到最高画质 (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 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);
        // 垂直方向在屏幕内,水平方向在左侧75%区域(避开评论)
        return (rect.top >= 0 && rect.bottom <= windowHeight) && (rect.left < windowWidth * 0.75);
    }

    // 3. 提示框 Toast
    function showToast(text) {
        const div = document.createElement('div');
        div.innerText = text;
        div.style.position = 'fixed';
        div.style.top = '10%'; div.style.left = '50%';
        div.style.transform = 'translate(-50%, -50%)';
        div.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        div.style.color = 'white'; div.style.padding = '8px 16px';
        div.style.borderRadius = '20px'; div.style.zIndex = '99999';
        div.style.fontSize = '14px'; div.style.pointerEvents = 'none';
        div.style.transition = 'opacity 0.5s';
        document.body.appendChild(div);
        setTimeout(() => {
            div.style.opacity = '0';
            setTimeout(() => div.remove(), 500);
        }, 1000);
    }

    // 4. 模拟指针事件 (用于点击画质菜单)
    function triggerPointerEvent(element, eventType) {
        if (!element) return;
        const event = new PointerEvent(eventType, {
            bubbles: true, cancelable: true, view: window,
            pointerId: 1, width: 1, height: 1, isPrimary: true, pointerType: 'mouse'
        });
        element.dispatchEvent(event);
    }

    // 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;
    }


    // ==========================================
    //            核心模块 A: 直播检测
    // ==========================================
    function checkLiveStream() {
        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; // 返回 true 表示检测到了直播,需要阻断后续逻辑
            }
        }
        return false; // 没有直播
    }


    // ==========================================
    //            核心模块 B: 画质调节
    // ==========================================
    function checkVideoQuality() {
        const video = document.querySelector('video');
        if (!video) return;

        // 1. 视频切换检测 (如果换了视频,重置画质检查状态)
        if (video.src !== lastVideoSrc) {
            console.log("[画质] 发现新视频,重置状态...");
            lastVideoSrc = video.src;
            isQualityChecked = false;
        }

        if (isQualityChecked) return;

        // 2. 寻找清晰度入口
        const triggerBtn = findResolutionButton();
        if (!triggerBtn) return;

        const currentText = triggerBtn.innerText;
        
        // 3. 检查是否达标
        if (currentText.includes("4K")) {
            isQualityChecked = true;
            return;
        }

        // 4. 执行操作 (模拟悬停)
        triggerPointerEvent(triggerBtn, 'pointerover');
        triggerPointerEvent(triggerBtn, 'pointerenter');

        // 5. 延时点击菜单
        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);
    }


    // ==========================================
    //               主控制循环
    // ==========================================
    function masterLoop() {
        // 第一步:优先检测是否为直播
        const isLive = checkLiveStream();

        // 如果检测到是直播(并且正在执行跳过),则直接结束本次循环
        // 只有当 isLive 为 false (不是直播) 时,才去检查画质
        if (!isLive) {
            checkVideoQuality();
        }
    }

    console.log('【抖音助手】二合一脚本已启动 (直播跳过 + 强力画质)');
    setInterval(masterLoop, MAIN_INTERVAL);

})();