Disable YouTube 60FPS (Force 30FPS)

Tells YouTube that your browser only supports videos at 30FPS or less, which switches all 60FPS videos to 30FPS and allows old computers to watch high-resolution videos without stutter!

As of 2016-09-23. See the latest version.

// ==UserScript==
// @name         Disable YouTube 60FPS (Force 30FPS)
// @namespace    SteveJobzniak
// @version      1.2
// @description  Tells YouTube that your browser only supports videos at 30FPS or less, which switches all 60FPS videos to 30FPS and allows old computers to watch high-resolution videos without stutter!
// @author       SteveJobzniak
// @match        *://www.youtube.com/*
// @exclude      *://www.youtube.com/tv*
// @exclude      *://www.youtube.com/embed/*
// @run-at       document-start
// @grant        none
// @noframes
// ==/UserScript==

/*
    This script tells YouTube that your browser only supports 30FPS or less,
    which means that you will see regular 30FPS versions of all HD videos.

    WHY DO THIS?:
      For my six year old laptop, switching from 1080p60 to 1080p30 reduces
      the CPU usage by 2-4x, and removes all CPU overloads that used to make
      my browser and video playback freeze! This means longer battery life,
      and a much happier video watching experience!

      (Furthermore, most older graphics cards only support hardware acceleration
      of 1080p30 or lower, which means that using this script may allow your
      graphics card to perform the video decoding for great battery savings!)

    INSTALLATION:
      Install the Tampermonkey (https://tampermonkey.net) extension for your
      specific browser, and then install this script into Tampermonkey.

      This script has been tested and confirmed working in Safari 9 for Mac
      and Google Chrome for Mac. But it should work in *all* browsers and OS's
      that support the Tampermonkey extension - on Windows, Mac and Linux!

      (This script does NOT work via Chrome's own basic built-in script support!)

    IMPORTANT NOTE TO ALL USERS:
      We DO NOT affect embedded YouTube videos, because embedded players
      *only* check for high-FPS support, so blocking those queries would
      mean completely losing *all* HD resolutions for embedded videos!

      I suggest clicking the "Watch on YouTube" button to play embedded
      high-FPS videos directly on YouTube in 30FPS instead!

    VERY IMPORTANT NOTE FOR SAFARI BROWSER USERS:
      This script contains a workaround for a Safari bug. The Safari browser
      uses "lazy" extension loading, which means that your extensions (such
      as Tampermonkey) don't start running in new tabs until you actually
      visit a webpage in your new tab. And if the first page you visit in your
      new tab is YouTube, it may perform its codec check *before* the extension
      has been fully loaded, in which case YouTube will revert to giving you high-FPS
      videos in that tab. This "too late extension loading" will happen every time
      you write/paste a YouTube video URL in a brand new empty tab, or right-click
      a video link and choose "open in new tab/window", or use the History menu
      to browse to a video page. In other words, it's quite rare but common
      enough to be annoying. Our chosen workaround is that whenever we detect
      that Safari has loaded Tampermonkey too late in the current tab, we perform
      a very quick reload of the current YouTube page so that the extension can
      run before YouTube does its codec check. This reloading is automatic and
      happens so quickly that most people won't even notice anything at all.
      I just mention it here for the few people who pay attention to such things.
*/
(function () {
    'use strict';

    function createNewTypeChecker( originalChecker, debugLogging )
    {
        return function( videoType ) {
            if( videoType === undefined ) { return false; }
            if( debugLogging ) { console.log('Format Query: "' + videoType + '", originalAnswer: "' + originalChecker( videoType ) + '"'); }

            // Block all queries regarding high-framerate support.
            var matches = videoType.match( /framerate=(\d+)/ );
            if( matches && ( matches[1] > 30 ) ) {
                if( debugLogging ) { console.log( 'Blocking High-FPS format: "' + videoType + '"' ); }
                return false;
            }

            // Let the browser answer all other codec queries.
            return originalChecker( videoType );
        };
    }

    /*
        Override the browser's Media Source Extensions codec checker,
        to tell YouTube that we don't support any formats above 30FPS.

        (It's very important that this userscript is @run-at document-start,
        before any of the YouTube scripts have had time to query the MSE!)
    */
    if( window.MediaSource ) {
        var originalChecker = window.MediaSource.isTypeSupported.bind( window.MediaSource );
        window.MediaSource.isTypeSupported = createNewTypeChecker( originalChecker, false );
    }

    /*
        Safari browser bug workaround (and any other browsers with the same bug):

        In the Safari browser, ALL new tabs/windows begin their life without
        *any* extensions loaded into memory. They're only loaded *after* you've
        actually visited at least one webpage in that tab. Then they stay loaded
        in that tab, except if you manually type a URL into the location bar or
        change webpage via the History menu, in which case Safari often unloads
        and then re-loads all extensions in that tab again.

        The result of this Safari behavior is that Tampermonkey MAY not
        always be immediately ready when you're visiting a YouTube video page.
        And if the extension is loaded *after* YouTube has already checked for
        supported video formats, then you'll be served with high-FPS video in
        that tab until you reload the webpage. Annoying!

        It happens in quite a LOT of situations, such as opening a brand new
        tab and typing/pasting the URL of a video into it and pressing enter,
        or visiting a video via your History menu, or right-clicking a video
        link and choosing "open in new tab/window", etc.

        The user can solve it by manually reloading the webpage after Tampermonkey
        is done initializing itself in that new tab, but it's such a common
        issue in Safari (it never happens in Google Chrome) that I decided
        to automate the page reloading process as follows:

        * This script is specified to run at "document-start" (before anything
          else on the YouTube webpage is loaded).
        * If we can find the "window.ytplayer" object, it means that we've been
          loaded TOO LATE, after YouTube has already performed its codec detection.
        * But if we're on the YouTube homepage or a search results page, then
          it doesn't MATTER if we're loaded late, since those pages don't contain
          any video players. (And forcing an auto-reload in those cases would
          just needlessly annoy people since it would happen every time time
          they manually type in "youtube.com".)
        * If we're loaded late on a video player page (/watch URL), then
          we automatically reload the webpage to try again. It causes a very,
          very brief (almost unnoticeable) flicker as it rapidly reloads that
          tab. That's the low price of fixing this annoying Safari bug! ;)
    */
    if( window.ytplayer ) {
        if( location.pathname && location.pathname === '/watch' ) {
            location.reload(); // reload the current video page
        }
    }
})();