Youtube Audio Mode

Listen to only the audio on YouTube without loading the video.

< Feedback on Youtube Audio Mode

Review: Good - script works

§
Posted: 2020-08-07

Thank you in advance. It worked perfectly if you can deploy it as chrome extension.

§
Posted: 2020-08-07

I just add isolation by video id for each video so now I can enable audio mode for specific video without effective other videos.

// ==UserScript==
// @name        Youtube Audio Mode
// @description Listen to only the audio on YouTube without loading the video.
// @version     1.2.2
// @include     https://www.youtube.com/*
// @license     GPL-3.0+; http://www.gnu.org/licenses/gpl-3.0.txt
// @run-at      document-end
// @grant       GM_xmlhttpRequest
// @grant       GM.setValue
// @grant       GM.getValue
// @noframes
// @namespace https://greasyfork.org/users/195276
// ==/UserScript==

(function(open) {
    window.addEventListener("yt-navigate-finish", audioMode);
    window.onYouTubeIframeAPIReady = audioMode();

    function gup( name, url ) {
        if (!url) url = location.href;
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( url );
        return results == null ? null : results[1];
    }

    async function getAudioMode(){
        return await GM.getValue("ytAudioMode:"+gup("v"));
    }

    async function setAudioMode(mode){
        return await GM.setValue("ytAudioMode:"+gup("v"), mode);
    }

    async function audioMode() {
        if (location.pathname == "/watch") {
            let video = document.getElementsByTagName("video")[0];
            let audioMode = await getAudioMode();
            addToMenu(audioMode);
            if (audioMode) {
                setPoster(video, ["maxres", "hq", "sd"]);
                watchStream(video);
            }
        }
    }

    // Watch the media streams so we can select the audio
    function watchStream(video) {
        XMLHttpRequest.prototype.open = function(method, url) {
            let validStream = /^(?!.*live=1).+audio.+$/;
            if (validStream.test(url) && ! video.src.includes("audio")) {
                video.pause();
                video.src = url.split("&range")[0];
                video.play();
            }
            open.apply(this, arguments);
        }
    }

    // Add audio mode to the settings menu
    async function addToMenu(audioMode) {
        let panel = document.getElementsByClassName("ytp-panel-menu")[0];
        if (!panel.innerHTML.includes("Audio Mode")) {
            panel.innerHTML += `
            <div class="ytp-menuitem"
                aria-checked="${audioMode}"
                id="audio-mode">
                <div class="ytp-menuitem-icon"></div>
                <div class="ytp-menuitem-label">Audio Mode</div>
                <div class="ytp-menuitem-content">
                    <div class="ytp-menuitem-toggle-checkbox">
                </div>
            </div>`;

            // Toggle audio mode on or off
            let audioToggle = document.getElementById("audio-mode");
            audioToggle.onclick = async function() {
                let audioMode = ! await getAudioMode();
                this.setAttribute("aria-checked", audioMode);

                setAudioMode(audioMode);
                location.reload();
            }
        }
    }

    // Set the video poster from thumbnails with the best avaliable format
    // https://developers.google.com/youtube/v3/docs/thumbnails
    async function setPoster(video, fmts) {
        let img = new Image();
        let videoId = location.search.match(/v=(.+?)(&|$)/)[1];
        img.src = `//i.ytimg.com/vi/${videoId}/${fmts.shift()}default.jpg`
        img.onload = function() {
            // A height 90 is YouTube"s not found image.
            if (img.height <= 90) {
                setPoster(video, fmts);
            } else {
                video.style.background = `url(${img.src}) no-repeat center`;
                video.style.backgroundSize = "contain";
            }
        };
    }
})(XMLHttpRequest.prototype.open);

Post reply

Sign in to post a reply.