YouTube Optimizador UI (Español)

Optimiza YouTube para un mejor rendimiento y experiencia mejorada.

Instalar este script¿?
Script recomendado por el autor

Puede que también te guste YouTube 30 FPS Forzado.

Instalar este script
// ==UserScript==
// @name         YouTube Optimizador UI (Español)
// @namespace    AkioBrian
// @version      2.2
// @description  Optimiza YouTube para un mejor rendimiento y experiencia mejorada.
// @license      MIT
// @author       AkioBrian
// @icon         https://i.imgur.com/gDJmU8b.png
// @match        https://www.youtube.com/*
// @match        https://youtube.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ===== CONFIGURACIÓN CON VALORES POR DEFECTO CONSISTENTES =====
    const DEFAULT_CONFIG = {
        removeElements: {
            sidebar: true,
            comments: false,
            shorts: true,
            endScreen: true,
            cards: true
        },
        performance: {
            reducePrefetch: true,
            tabManagement: false,
            memoryCleanup: true
        },
        ui: {
            minimalTheme: true,
        }
    };

    let CONFIG = {
        removeElements: {
            sidebar: GM_getValue('sidebar', DEFAULT_CONFIG.removeElements.sidebar),
            comments: GM_getValue('comments', DEFAULT_CONFIG.removeElements.comments),
            shorts: GM_getValue('shorts', DEFAULT_CONFIG.removeElements.shorts),
            endScreen: GM_getValue('endScreen', DEFAULT_CONFIG.removeElements.endScreen),
            cards: GM_getValue('cards', DEFAULT_CONFIG.removeElements.cards)
        },
        performance: {
            reducePrefetch: GM_getValue('reducePrefetch', DEFAULT_CONFIG.performance.reducePrefetch),
            tabManagement: GM_getValue('tabManagement', DEFAULT_CONFIG.performance.tabManagement),
            memoryCleanup: GM_getValue('memoryCleanup', DEFAULT_CONFIG.performance.memoryCleanup)
        },
        ui: {
            minimalTheme: GM_getValue('minimalTheme', DEFAULT_CONFIG.ui.minimalTheme),
        }
    };

    // ===== VARIABLES GLOBALES PARA CLEANUP =====
    let observers = [];
    let intervals = [];
    let originalFetch = null;
    let isVisible = !document.hidden;

    // ===== UTILIDADES =====
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    function addObserver(observer) {
        observers.push(observer);
        return observer;
    }

    function addInterval(interval) {
        intervals.push(interval);
        return interval;
    }

    function cleanup() {
        observers.forEach(observer => observer.disconnect());
        intervals.forEach(interval => clearInterval(interval));
        observers = [];
        intervals = [];

        if (originalFetch && window.fetch !== originalFetch) {
            window.fetch = originalFetch;
        }
    }

    // ===== MENÚ DE CONFIGURACIÓN =====
    function createMenuCommands() {
        const menuItems = [
            ['sidebar', '🔲 Sidebar', 'removeElements'],
            ['comments', '💬 Comentarios', 'removeElements'],
            ['shorts', '📱 Shorts', 'removeElements'],
            ['endScreen', '🎬 Pantalla Final', 'removeElements'],
            ['cards', '🃏 Tarjetas', 'removeElements'],
            ['reducePrefetch', '⚡ Reducir Precarga', 'performance'],
            ['tabManagement', '📑 Gestión Pestañas', 'performance'],
            ['memoryCleanup', '🧹 Limpieza Memoria', 'performance'],
            ['minimalTheme', '🌙 Oscuro Optimizado', 'ui'],
        ];

        menuItems.forEach(([key, label, category]) => {
            const currentValue = CONFIG[category][key];
            const statusText = category === 'removeElements'
                ? (currentValue ? 'OCULTO' : 'VISIBLE')
                : (currentValue ? 'ON' : 'OFF');

            GM_registerMenuCommand(`${label}: ${statusText}`, () => {
                CONFIG[category][key] = !CONFIG[category][key];
                GM_setValue(key, CONFIG[category][key]);
                location.reload();
            });
        });

        GM_registerMenuCommand('🔄 Restablecer Configuración', () => {
            if (confirm('¿Restablecer toda la configuración a valores por defecto?')) {
                Object.keys(DEFAULT_CONFIG).forEach(category => {
                    Object.keys(DEFAULT_CONFIG[category]).forEach(key => {
                        GM_setValue(key, DEFAULT_CONFIG[category][key]);
                    });
                });
                location.reload();
            }
        });
    }

    // ===== CSS INMEDIATO CON SELECTORES ROBUSTOS =====
    function injectImmediateCSS() {
        const style = document.createElement('style');
        let cssContent = '';

        if (CONFIG.removeElements.sidebar) {
            cssContent += `
                #secondary:not([hidden]),
                ytd-watch-next-secondary-results-renderer:not([hidden]),
                #related:not([hidden]),
                [class*="secondary-results"]:not([hidden]) {
                    display: none !important;
                }
            `;
        }

        if (CONFIG.removeElements.comments) {
            cssContent += `
                #comments:not([hidden]),
                ytd-comments:not([hidden]),
                [id*="comment"]:not([hidden]),
                [class*="comment"]:not(.comment-button):not([hidden]) {
                    display: none !important;
                }
            `;
        }

        if (CONFIG.removeElements.shorts) {
            cssContent += `
                ytd-reel-shelf-renderer:not([hidden]),
                [is-shorts]:not([hidden]),
                [class*="shorts"]:not([hidden]),
                ytd-rich-section-renderer[is-shorts]:not([hidden]) {
                    display: none !important;
                }
            `;
        }

        if (CONFIG.removeElements.endScreen) {
            cssContent += `
                .ytp-ce-element:not([hidden]),
                .ytp-endscreen-element:not([hidden]) {
                    display: none !important;
                }
            `;
        }

        if (CONFIG.removeElements.cards) {
            cssContent += `
                .ytp-cards-teaser:not([hidden]),
                .ytp-card:not([hidden]),
                .ytp-cards-button:not([hidden]),
                [class*="card"]:not(.yt-card):not([hidden]) {
                    display: none !important;
                }
            `;
        }

        style.textContent = cssContent;
        style.id = 'youtube-optimizer-css';

        const injectCSS = () => {
            if (document.head) {
                const existing = document.getElementById('youtube-optimizer-css');
                if (existing) existing.remove();
                document.head.appendChild(style);
            }
        };

        if (document.head) {
            injectCSS();
        } else {
            const headObserver = addObserver(new MutationObserver(() => {
                if (document.head) {
                    injectCSS();
                    headObserver.disconnect();
                }
            }));
            headObserver.observe(document.documentElement, { childList: true });
        }
    }

    // ===== INTERCEPTACIÓN DE RED MEJORADA =====
    function interceptNetworkResponses() {
        if (originalFetch) return; // Evitar múltiples interceptaciones

        originalFetch = window.fetch;
        window.fetch = function(...args) {
            return originalFetch.apply(this, args).then(response => {
                const url = typeof args[0] === 'string' ? args[0] : args[0]?.url;

                if (!url || !url.includes('youtube.com')) {
                    return response;
                }

                // Solo interceptar URLs relevantes de YouTube
                const relevantEndpoints = ['next', 'watch', 'browse'];
                const isRelevant = relevantEndpoints.some(endpoint => url.includes(endpoint));

                if (!isRelevant) {
                    return response;
                }

                const contentType = response.headers.get('content-type');
                if (!contentType || !contentType.includes('application/json')) {
                    return response;
                }

                return response.clone().text().then(data => {
                    try {
                        let jsonData = JSON.parse(data);
                        let modified = false;

                        // Validar estructura antes de modificar
                        if (jsonData && typeof jsonData === 'object') {
                            // Remover sidebar
                            if (CONFIG.removeElements.sidebar &&
                                jsonData.contents?.twoColumnWatchNextResults?.secondaryResults) {
                                delete jsonData.contents.twoColumnWatchNextResults.secondaryResults;
                                modified = true;
                            }

                            // Remover comentarios
                            if (CONFIG.removeElements.comments &&
                                jsonData.contents?.twoColumnWatchNextResults?.results?.results?.contents) {
                                const originalLength = jsonData.contents.twoColumnWatchNextResults.results.results.contents.length;
                                jsonData.contents.twoColumnWatchNextResults.results.results.contents =
                                    jsonData.contents.twoColumnWatchNextResults.results.results.contents.filter(item =>
                                        !item.itemSectionRenderer?.targetId?.includes('comments')
                                    );
                                modified = originalLength !== jsonData.contents.twoColumnWatchNextResults.results.results.contents.length;
                            }
                        }

                        if (modified) {
                            return new Response(JSON.stringify(jsonData), {
                                status: response.status,
                                statusText: response.statusText,
                                headers: response.headers
                            });
                        }
                    } catch (error) {
                        console.warn('YouTube Optimizer: Error parsing JSON response:', error);
                    }

                    return response;
                }).catch(() => response);
            }).catch(error => {
                console.warn('YouTube Optimizer: Fetch interceptor error:', error);
                throw error;
            });
        };
    }

    // ===== OPTIMIZACIONES DE RENDIMIENTO =====
    function optimizeVideoPrefetch() {
        if (!CONFIG.performance.reducePrefetch) return;

        const style = document.createElement('style');
        style.textContent = `
            ytd-thumbnail img {
                loading: lazy !important;
            }
            video:not(.video-stream) {
                preload: none !important;
            }
            ytd-thumbnail:hover img {
                transition: none !important;
            }
            [class*="thumbnail"] img {
                loading: lazy !important;
            }
        `;
        style.id = 'youtube-optimizer-prefetch';
        document.head?.appendChild(style);
    }

    // ===== GESTIÓN DE PESTAÑAS MEJORADA =====
    function setupTabManagement() {
        if (!CONFIG.performance.tabManagement) return;

        function handleVisibilityChange() {
            const videos = document.querySelectorAll('video');

            if (document.hidden && isVisible) {
                videos.forEach(video => {
                    if (!video.paused) {
                        video.pause();
                        video.dataset.wasPausedByOptimizer = 'true';
                    }
                });
                isVisible = false;
            } else if (!document.hidden && !isVisible) {
                isVisible = true;
                // No resumir automáticamente - usuario debe decidir
            }
        }

        document.addEventListener('visibilitychange', handleVisibilityChange);
    }

    // ===== LIMPIEZA DE MEMORIA CON INTERSECTION OBSERVER =====
    function setupMemoryCleanup() {
        if (!CONFIG.performance.memoryCleanup) return;

        // Intersection Observer para elementos fuera del viewport
        const intersectionObserver = addObserver(new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (!entry.isIntersecting) {
                    const element = entry.target;
                    // Limpiar solo elementos no visibles hace más de 30 segundos
                    if (!element.dataset.lastVisible) {
                        element.dataset.lastVisible = Date.now();
                    } else if (Date.now() - element.dataset.lastVisible > 30000) {
                        element.remove();
                        intersectionObserver.unobserve(element);
                    }
                } else {
                    entry.target.dataset.lastVisible = Date.now();
                }
            });
        }, { threshold: 0 }));

        // Observer para nuevos elementos
        const elementObserver = addObserver(new MutationObserver(debounce((mutations) => {
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // Element node
                        const cleanableElements = node.querySelectorAll?.('ytd-thumbnail, ytd-video-renderer, ytd-comment-thread-renderer') || [];
                        cleanableElements.forEach(el => intersectionObserver.observe(el));
                    }
                });
            });
        }, 1000)));

        elementObserver.observe(document.body, { childList: true, subtree: true });

        // Limpieza periódica más eficiente
        const cleanupInterval = addInterval(setInterval(() => {
            // Forzar garbage collection si está disponible
            if (typeof window.gc === 'function') {
                window.gc();
            }

            // Limpiar elementos marcados para eliminación
            document.querySelectorAll('[data-last-visible]').forEach(el => {
                if (Date.now() - parseInt(el.dataset.lastVisible) > 60000 && el.offsetParent === null) {
                    el.remove();
                }
            });
        }, 60000));
    }

    // ===== TEMA OSCURO OPTIMIZADO =====
    function applyCustomTheme() {
        if (!CONFIG.ui.minimalTheme) return;

        const themeStyles = `
            html[dark] {
                --yt-spec-brand-background-solid: #000000 !important;
                --yt-spec-general-background-a: #000000 !important;
                --yt-spec-general-background-b: #101010 !important;
                --yt-spec-general-background-c: #151515 !important;
                --yt-spec-text-primary: #d9d9d9 !important;
                --yt-spec-text-secondary: #bbbbbb !important;
            }
            ytd-thumbnail-overlay-resume-playback-renderer,
            ytd-thumbnail-overlay-time-status-renderer {
                opacity: 0.7 !important;
            }
            ytd-video-renderer,
            ytd-rich-item-renderer {
                border-radius: 8px !important;
                transition: none !important;
            }
            ytd-video-renderer:hover,
            ytd-rich-item-renderer:hover {
                transform: none !important;
                box-shadow: none !important;
            }
            ::-webkit-scrollbar {
                width: 6px !important;
            }
            ::-webkit-scrollbar-track {
                background: transparent !important;
            }
            ::-webkit-scrollbar-thumb {
                background: #666 !important;
                border-radius: 3px !important;
            }
            ytd-masthead[dark] {
                border-bottom: none !important;
            }
            .ytp-gradient-bottom {
                background: linear-gradient(transparent, rgba(0,0,0,0.2)) !important;
            }
        `;

        const style = document.createElement('style');
        style.textContent = themeStyles;
        style.id = 'youtube-optimizer-theme';
        document.head?.appendChild(style);
    }

    // ===== LIMPIEZA FALLBACK MEJORADA =====
    function setupFallbackCleanup() {
        const cleanupActions = {
            sidebar: () => CONFIG.removeElements.sidebar &&
                document.querySelectorAll('#secondary, ytd-watch-next-secondary-results-renderer').forEach(el => el?.remove()),
            comments: () => CONFIG.removeElements.comments &&
                document.querySelectorAll('#comments, ytd-comments#comments').forEach(el => el?.remove()),
            shorts: () => CONFIG.removeElements.shorts &&
                document.querySelectorAll('ytd-reel-shelf-renderer, ytd-rich-section-renderer[is-shorts]').forEach(el => el?.remove()),
            endScreen: () => CONFIG.removeElements.endScreen &&
                document.querySelectorAll('.ytp-ce-element, .ytp-endscreen-element').forEach(el => el?.remove()),
            cards: () => CONFIG.removeElements.cards &&
                document.querySelectorAll('.ytp-cards-teaser, .ytp-card').forEach(el => el?.remove())
        };

        const executeCleanup = debounce(() => {
            try {
                Object.values(cleanupActions).forEach(action => action());
            } catch (error) {
                console.warn('YouTube Optimizer: Cleanup error:', error);
            }
        }, 500);

        // Ejecutar limpieza inicial
        executeCleanup();

        // Observer con debounce para cambios en el DOM
        const cleanupObserver = addObserver(new MutationObserver(executeCleanup));
        cleanupObserver.observe(document.body, {
            childList: true,
            subtree: false,
            attributes: false
        });
    }

    // ===== INICIALIZACIÓN =====
    function init() {
        console.log('🚀 YouTube Optimizador UI v2.2 activado');

        // Limpiar estado previo en navegación SPA
        cleanup();

        createMenuCommands();
        injectImmediateCSS();
        interceptNetworkResponses();
        optimizeVideoPrefetch();
        applyCustomTheme();

        const initializeWhenReady = () => {
            setupTabManagement();
            setupMemoryCleanup();
            setupFallbackCleanup();
        };

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initializeWhenReady, { once: true });
        } else {
            initializeWhenReady();
        }

        // Manejo de navegación SPA mejorado
        let lastUrl = location.href;
        const navigationObserver = addObserver(new MutationObserver(debounce(() => {
            if (location.href !== lastUrl) {
                lastUrl = location.href;
                // Re-aplicar solo lo necesario después de navegación
                setTimeout(() => {
                    injectImmediateCSS();
                    setupFallbackCleanup();
                }, 500);
            }
        }, 100)));

        navigationObserver.observe(document.body, {
            childList: true,
            subtree: false
        });

        // Cleanup al salir de la página
        window.addEventListener('beforeunload', cleanup, { once: true });
    }

    // Iniciar el script
    init();

})();