Youtube Highest Quality

Automatically selects the best available video quality on YouTube.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Youtube Highest Quality
// @author       tzshuhag
// @namespace    http://tampermonkey.net/
// @version      1.0
// @match        *://www.youtube.com/*
// @match        *://m.youtube.com/*
// @match        *://www.youtube-nocookie.com/*
// @exclude      *://www.youtube.com/live_chat*
// @homepageURL  https://tzshuhag.me
// @icon         https://raw.githubusercontent.com/tz-shuhag/YT-HD/refs/heads/main/128.png
// @grant        none
// @run-at       document-idle
// @license      MIT
// @description  Automatically selects the best available video quality on YouTube.
// ==/UserScript==
 
/* jshint esversion: 11 */
 
(async function () {
    'use strict';
 
    const QUALITIES = {
        highres: 4320,
        hd2160: 2160,
        hd1440: 1440,
        hd1080: 1080,
        hd720: 720,
        large: 480,
        medium: 360,
        small: 240,
        tiny: 144
    };
 
    const PREMIUM_INDICATOR_LABEL = "Premium";
 
    // Global variables
    let moviePlayer = null;
    let isIframe = false;
 
    async function setResolution() {
        if (!moviePlayer) {
            console.log('Movie player not found.');
            return;
        }
 
        // Debounce to prevent rapid calls
        let debounceTimer;
        if (debounceTimer) clearTimeout(debounceTimer);
        debounceTimer = setTimeout(async () => {
            try {
                const videoQualityData = moviePlayer.getAvailableQualityData();
                if (!videoQualityData.length) {
                    console.log('No quality data available, waiting for playback...');
                    const videoElement = moviePlayer.querySelector('video');
                    if (videoElement && videoElement.paused) {
                        videoElement.addEventListener('play', setResolution, { once: true });
                    }
                    return;
                }
 
                const availableQualities = moviePlayer.getAvailableQualityLevels();
                const highestQuality = availableQualities.reduce((max, q) => 
                    QUALITIES[q] > QUALITIES[max] ? q : max, availableQualities[0]);
                const premiumData = videoQualityData.find(q =>
                    q.quality === highestQuality &&
                    q.qualityLabel?.trim().endsWith(PREMIUM_INDICATOR_LABEL) &&
                    q.isPlayable
                );
 
                moviePlayer.setPlaybackQualityRange(highestQuality, highestQuality, premiumData?.formatId);
                console.log(`Set quality to: [${highestQuality}${premiumData ? ' Premium' : ''}]`);
            } catch (error) {
                console.error('Failed to set resolution:', error);
            }
        }, 100);
    }
 
    function processVideoLoad(event = null) {
        console.log('Processing video load...');
        moviePlayer = event?.target?.player_ ?? document.querySelector('#movie_player');
        if (moviePlayer) setResolution();
    }
 
    function addEventListeners() {
        if (window.location.hostname === 'm.youtube.com') {
            window.addEventListener('state-navigateend', processVideoLoad, true);
        } else {
            window.addEventListener('yt-player-updated', processVideoLoad, true);
        }
    }
 
    async function initialize() {
        if (window.self !== window.top) isIframe = true;
        window.addEventListener('pageshow', processVideoLoad, true);
        addEventListeners();
    }
 
    function hasGreasyMonkeyAPI() {
        return typeof GM !== 'undefined' || typeof GM_info !== 'undefined';
    }
 
    if (hasGreasyMonkeyAPI()) {
        initialize();
    } else {
        console.error('No Grease Monkey API detected.');
    }
})();