logo NodeSeekbeta

用AI搓了两个youtube 详细统计信息 精简版

在chrome和firefox浏览器测过,其他未知...
使用方法:安装Tampermonkey(篡改猴),添加新脚本,复制并粘贴脚本后按Ctrl+s保存,打开详细统计信息。

迷你版 v2.4 优化

g4GWxzfNhmWfHLxtya8cfJoXD2YN9eEE.webp|539x189

// ==UserScript==
// @name         YouTube Stats for Mini 迷你版 v2.4
// @namespace    http://tampermonkey.net/
// @version      2.4
// @description  YouTube Stats for Mini(直播/拖动进度条稳定|同步压制 pl_i / pbs)
// @author       jian
// @match        *://www.youtube.com/*
// @match        *://m.youtube.com/*
// @grant        GM_addStyle
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    /* ================= 样式 ================= */
    GM_addStyle(`
        .html5-video-info-panel.ytp-sfn {
            position: absolute !important;
            top: 10px !important;
            left: 10px !important;
            z-index: 99999 !important;
            opacity: 0.82 !important;
            font-size: 11px !important;
            width: 410px !important;
            max-width: 410px !important;
            background: rgba(0, 0, 0, 0.68) !important;
            border-radius: 4px;
            overflow: hidden !important;
        }

        .html5-video-info-panel.ytp-sfn
        .html5-video-info-panel-content > div {
            white-space: normal !important;
            min-height: 0 !important;
        }

        .yt-mbps {
            margin-left: auto;
            margin-right: 18px;
            padding-left: 8px;
            white-space: nowrap;
            color: #ff8c00;
            font-weight: bold;
        }

        .html5-video-info-panel.ytp-sfn
        .ytp-horizonchart {
            width: 190px !important;
            max-width: 190px !important;
        }

        .html5-video-info-panel.ytp-sfn
        .ytp-horizonchart canvas {
            width: 190px !important;
        }
    `);

    /* ================= 白名单 ================= */
    const ALLOWED = new Set([
        'Viewport / Frames',
        'Current / Optimal Res',
        'Connection Speed',
        'Network Activity',
        'Buffer Health'
    ]);

    /* ================= 行级清理(物理移除) ================= */
    function cleanRows(panel) {
        const content = panel.querySelector('.html5-video-info-panel-content');
        if (!content) return;

        [...content.children].forEach(row => {
            const label = row.querySelector(':scope > div:first-child');
            const title = label?.textContent?.trim() || '';

            // 无标题 / 非白名单 / 明确垃圾行
            if (
                !ALLOWED.has(title) ||
                title === 'Color' ||
                title === '' ||
                /pl_i:|pbs:|SABR|Mystery/i.test(row.textContent)
            ) {
                row.remove(); // 🔥 直接移除,永不参与 layout
            } else {
                row.style.display = 'flex';
            }
        });
    }

    /* ================= MB/s 注入 ================= */
    function setupSpeed(panel) {
        const rows = panel.querySelectorAll('.html5-video-info-panel-content > div');
        let kbpsSpan, resRow;

        rows.forEach(row => {
            const label = row.querySelector(':scope > div:first-child');
            if (!label) return;

            const title = label.textContent.trim();
            if (title === 'Connection Speed') {
                kbpsSpan = row.querySelector('span span:last-child, span:last-child');
            }
            if (title === 'Current / Optimal Res') {
                resRow = row;
            }
        });

        if (!kbpsSpan || !resRow) return;

        let mbpsSpan = resRow.querySelector('.yt-mbps');
        if (!mbpsSpan) {
            mbpsSpan = document.createElement('span');
            mbpsSpan.className = 'yt-mbps';
            resRow.appendChild(mbpsSpan);
        }

        const update = () => {
            const m = kbpsSpan.textContent.match(/([\d.]+)\s*Kbps/i);
            if (!m) return;
            mbpsSpan.textContent = `${(m[1] / 8 / 1024).toFixed(2)} MB/s`;
        };

        update();
        new MutationObserver(update).observe(kbpsSpan, {
            childList: true,
            characterData: true,
            subtree: true
        });
    }

    /* ================= 内容级同步 Observer ================= */
    function observeContent(panel) {
        if (panel._contentObserver) return;

        const content = panel.querySelector('.html5-video-info-panel-content');
        if (!content) return;

        const observer = new MutationObserver(() => cleanRows(panel));
        observer.observe(content, { childList: true, subtree: true });

        panel._contentObserver = observer;
    }

    /* ================= 高频短时压制 ================= */
    function reinforceClean(panel, duration = 2000, interval = 60) {
        const start = performance.now();
        const timer = setInterval(() => {
            if (!document.body.contains(panel)) {
                clearInterval(timer);
                return;
            }
            cleanRows(panel);
            setupSpeed(panel);
            if (performance.now() - start > duration) clearInterval(timer);
        }, interval);
    }

    /* ================= Stats 出现监听 ================= */
    function setupPanelObserver() {
        new MutationObserver(muts => {
            for (const m of muts) {
                for (const node of m.addedNodes) {
                    if (node.nodeType !== 1) continue;

                    const panel = node.classList?.contains('html5-video-info-panel')
                        ? node
                        : node.querySelector?.('.html5-video-info-panel');

                    if (!panel) continue;

                    const player =
                        document.querySelector('#movie_player') ||
                        document.querySelector('.html5-video-player');

                    if (player && panel.parentElement !== player) {
                        player.appendChild(panel);
                    }

                    setTimeout(() => {
                        cleanRows(panel);
                        setupSpeed(panel);
                        observeContent(panel);
                        reinforceClean(panel, 2500, 60);
                    }, 30);
                }
            }
        }).observe(document.body, { childList: true, subtree: true });
    }

    /* ================= 播放器事件兜底 ================= */
    function setupVideoListener() {
        const video = document.querySelector('video');
        if (!video) return;

        video.addEventListener('seeked', () => {
            const panel = document.querySelector('.html5-video-info-panel.ytp-sfn');
            if (!panel) return;
            cleanRows(panel);
            reinforceClean(panel, 1200, 60);
        });

        video.addEventListener('timeupdate', () => {
            const panel = document.querySelector('.html5-video-info-panel.ytp-sfn');
            if (panel) cleanRows(panel);
        });
    }

    function init() {
        setupPanelObserver();
        setupVideoListener();
    }

    document.readyState === 'loading'
        ? document.addEventListener('DOMContentLoaded', init)
        : init();

})();


单行可拖动版

ECZMMQ17naWz2zE5Ir9GTGqVPLib3r3O.webp|439x143

// ==UserScript==
// @name         YouTube Stats (单行可拖动版 Kbps+MB/s 1.7)
// @namespace    http://tampermonkey.net/
// @version      1.7
// @description  优化字符补位,缩短间距,显示更紧凑。
// @author       jian
// @match        *://www.youtube.com/*
// @match        *://m.youtube.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const POS_KEY = 'yt-custom-speed-pos';
    const OVERLAY_ID = 'yt-custom-speed-overlay';

    let lastKbps = "0";
    let lastMBps = "0.00";
    let lastBuffer = "0.0";
    let panelActive = false;
    let userClosed = false;
    let lastNativeVisible = false;

    const style = document.createElement('style');
    style.textContent = `
        .html5-video-info-panel { opacity: 0 !important; pointer-events: none !important; visibility: hidden !important; }
        #${OVERLAY_ID} {
            position: absolute;
            padding: 5px 10px;
            border-radius: 6px;
            background: rgba(0,0,0,0.5);
            color: #fff;
            font-size: 12px;
            font-family: 'Consolas', 'Monaco', monospace;
            white-space: pre;
            cursor: move;
            user-select: none;
            line-height: 1.2;
            z-index: 999999;
            display: none;
            /* 进一步减小最小宽度,让框体紧贴文字 */
            min-width: 220px;
            align-items: center;
            justify-content: space-between;
        }
        #${OVERLAY_ID} .close-btn {
            margin-left: 8px;
            font-size: 16px;
            color: rgba(255,255,255,0.4);
            cursor: pointer;
            flex-shrink: 0;
            line-height: 1;
        }
        #${OVERLAY_ID} .close-btn:hover { color: #ff4d4d; }
    `;
    document.documentElement.appendChild(style);

    function calcMBps(kbps) {
        return (kbps / 8 / 1024).toFixed(2);
    }

    function createOverlay() {
        let box = document.getElementById(OVERLAY_ID);
        if (!box) {
            const player = document.querySelector('#movie_player') || document.querySelector('.html5-video-player');
            if (!player) return null;

            box = document.createElement('div');
            box.id = OVERLAY_ID;

            const textSpan = document.createElement('span');
            textSpan.id = `${OVERLAY_ID}-text`;
            box.appendChild(textSpan);

            const closeBtn = document.createElement('span');
            closeBtn.className = 'close-btn';
            closeBtn.textContent = '×';

            closeBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                userClosed = true;
                const nativeCloseBtn = document.querySelector('.html5-video-info-panel button.html5-video-info-panel-close');
                if (nativeCloseBtn) nativeCloseBtn.click();
                box.style.display = 'none';
            });

            box.appendChild(closeBtn);
            const pos = JSON.parse(localStorage.getItem(POS_KEY)) || { left: '20px', top: '20px' };
            Object.assign(box.style, { left: pos.left, top: pos.top });
            enableDrag(box);
            player.appendChild(box);
        }
        return box;
    }

    function enableDrag(el) {
        let dragging = false;
        let startX, startY, startLeft, startTop;
        const start = e => {
            if (e.target.className === 'close-btn') return;
            dragging = true;
            const p = e.touches ? e.touches[0] : e;
            startX = p.clientX; startY = p.clientY;
            startLeft = el.offsetLeft; startTop = el.offsetTop;
            e.stopPropagation();
        };
        const move = e => {
            if (!dragging) return;
            const p = e.touches ? e.touches[0] : e;
            el.style.left = (startLeft + p.clientX - startX) + 'px';
            el.style.top = (startTop + p.clientY - startY) + 'px';
        };
        const end = () => {
            if (dragging) {
                dragging = false;
                localStorage.setItem(POS_KEY, JSON.stringify({ left: el.style.left, top: el.style.top }));
            }
        };
        el.addEventListener('mousedown', start);
        document.addEventListener('mousemove', move);
        document.addEventListener('mouseup', end);
    }

    function fetchData() {
        const nativePanel = document.querySelector('.html5-video-info-panel');
        const isNowVisible = !!(nativePanel && nativePanel.offsetParent !== null);

        if (isNowVisible && !lastNativeVisible) userClosed = false;
        lastNativeVisible = isNowVisible;
        panelActive = isNowVisible;

        if (nativePanel) {
            const raw = nativePanel.textContent || "";
            const sMatch = raw.match(/(\d+)\s*Kbps/i);
            if (sMatch && sMatch[1]) {
                lastKbps = sMatch[1];
                lastMBps = calcMBps(parseInt(lastKbps));
            }
            const bMatch = raw.match(/([\d.]+)\s*s/);
            if (bMatch && bMatch[1]) lastBuffer = bMatch[1];
        }
    }

    function updateOverlay() {
        const box = createOverlay();
        if (!box) return;

        if (!panelActive || userClosed) {
            box.style.display = 'none';
            return;
        }

        const textSpan = box.querySelector(`#${OVERLAY_ID}-text`);

        // --- 紧凑对齐逻辑 ---
        const kbpsStr = lastKbps.padStart(6, ' ');   // 网速 6 位
        const mbpsStr = lastMBps.padStart(5, ' ');   // MB/s 5 位 (xx.xx)
        const bufferStr = lastBuffer.padStart(5, ' '); // 缓冲 5 位 (xx.xx)

        // 缩短符号间的空格
        textSpan.textContent = `速度:${kbpsStr}Kbps → ${mbpsStr}MB/s 缓冲:${bufferStr}s`;
        box.style.display = 'flex';
    }

    setInterval(() => {
        fetchData();
        updateOverlay();
    }, 300);

})();

在加一个两行版

9F5PzGy4iLi2fJNWtbYRLEgYIHo1HdmZ.webp

// ==UserScript==
// @name         YouTube Stats 两行版
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  YouTube Stats 两行版
// @author       jian
// @match        *://www.youtube.com/*
// @match        *://m.youtube.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const POS_KEY = 'yt-custom-speed-pos';
    const OVERLAY_ID = 'yt-custom-speed-overlay';

    let lastMBps = "0.00";
    let lastBuffer = "0.00";
    let panelActive = false;
    let userClosed = false;
    let lastNativeVisible = false;

    const style = document.createElement('style');
    style.textContent = `
        .html5-video-info-panel { opacity: 0 !important; pointer-events: none !important; visibility: hidden !important; }
        #${OVERLAY_ID} {
            position: absolute;
            padding: 4px 8px;
            border-radius: 4px;
            background: rgba(0,0,0,0.55);
            color: #fff;
            font-size: 12px;
            font-family: 'Consolas', 'Monaco', monospace;
            white-space: nowrap;
            cursor: move;
            user-select: none;
            line-height: 1.4;
            z-index: 999999;
            display: none;
            align-items: center;
            border: 1px solid rgba(255,255,255,0.1);
        }
        #${OVERLAY_ID} .stats-text {
            display: block;
            white-space: pre;
        }
        #${OVERLAY_ID} .close-btn {
            margin-left: 8px;
            font-size: 16px;
            color: rgba(255,255,255,0.3);
            cursor: pointer;
            line-height: 1;
        }
        #${OVERLAY_ID} .close-btn:hover { color: #ff4d4d; }
    `;
    document.documentElement.appendChild(style);

    function calcMBps(kbps) {
        return (kbps / 8 / 1024).toFixed(2);
    }

    function createOverlay() {
        let box = document.getElementById(OVERLAY_ID);
        if (!box) {
            const player = document.querySelector('#movie_player') || document.querySelector('.html5-video-player');
            if (!player) return null;

            box = document.createElement('div');
            box.id = OVERLAY_ID;

            const textSpan = document.createElement('span');
            textSpan.className = 'stats-text';
            textSpan.id = `${OVERLAY_ID}-text`;
            box.appendChild(textSpan);

            const closeBtn = document.createElement('span');
            closeBtn.className = 'close-btn';
            closeBtn.textContent = '×';
            closeBtn.onclick = (e) => {
                e.stopPropagation();
                userClosed = true;
                const nativeCloseBtn = document.querySelector('.html5-video-info-panel button.html5-video-info-panel-close');
                if (nativeCloseBtn) nativeCloseBtn.click();
                box.style.display = 'none';
            };

            box.appendChild(closeBtn);
            const pos = JSON.parse(localStorage.getItem(POS_KEY)) || { left: '20px', top: '20px' };
            Object.assign(box.style, { left: pos.left, top: pos.top });
            enableDrag(box);
            player.appendChild(box);
        }
        return box;
    }

    function enableDrag(el) {
        let dragging = false, startX, startY, startLeft, startTop;
        el.addEventListener('mousedown', e => {
            if (e.target.className === 'close-btn') return;
            dragging = true;
            const p = e.touches ? e.touches[0] : e;
            startX = p.clientX; startY = p.clientY;
            startLeft = el.offsetLeft; startTop = el.offsetTop;
            e.stopPropagation();
        });
        document.addEventListener('mousemove', e => {
            if (!dragging) return;
            const p = e.touches ? e.touches[0] : e;
            el.style.left = (startLeft + p.clientX - startX) + 'px';
            el.style.top = (startTop + p.clientY - startY) + 'px';
        });
        document.addEventListener('mouseup', () => {
            if (dragging) {
                dragging = false;
                localStorage.setItem(POS_KEY, JSON.stringify({ left: el.style.left, top: el.style.top }));
            }
        });
    }

    function fetchData() {
        const nativePanel = document.querySelector('.html5-video-info-panel');
        const isNowVisible = !!(nativePanel && nativePanel.offsetParent !== null);
        if (isNowVisible && !lastNativeVisible) userClosed = false;
        lastNativeVisible = isNowVisible;
        panelActive = isNowVisible;

        if (nativePanel) {
            const raw = nativePanel.textContent || "";
            const sMatch = raw.match(/(\d+)\s*Kbps/i);
            if (sMatch) lastMBps = calcMBps(parseInt(sMatch[1]));
            const bMatch = raw.match(/([\d.]+)\s*s/);
            if (bMatch) lastBuffer = parseFloat(bMatch[1]).toFixed(2);
        }
    }

    function updateOverlay() {
        const box = createOverlay();
        if (!box || !panelActive || userClosed) {
            if(box) box.style.display = 'none';
            return;
        }

        const textSpan = box.querySelector(`#${OVERLAY_ID}-text`);

        // 核心修改:为数值设置 5 位最小宽度占位,单位后紧跟末尾
        // padStart(5) 确保像 "1.23" 这种 4 位数前面补一个空格对齐 "12.34"
        const speedVal = lastMBps.padStart(5, ' ');
        const bufferVal = lastBuffer.padStart(5, ' ');

        textSpan.textContent = `速度:${speedVal}MB/s\n缓冲:${bufferVal}s`;
        box.style.display = 'flex';
    }

    setInterval(() => {
        fetchData();
        updateOverlay();
    }, 300);

})();

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有71941位seeker

🎉欢迎新用户🎉