YouTube Audio Recorder v1.9

Add a download button for YouTube!

目前為 2018-01-07 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name YouTube Audio Recorder v1.9
// @description Add a download button for YouTube!
// @namespace https://greasyfork.org/
// @homepageURL https://greasyfork.org/scripts/34613
// @supportURL https://greasyfork.org/scripts/34613/feedback
// @author Punisher
// @version 1.9
// @date 2018-01-07
// @compatible chrome
// @compatible firefox
// @compatible opera
// @compatible safari
// @license GNU GPL v3.0 or later. http://www.gnu.org/copyleft/gpl.html
// @include http://www.youtube.com/*
// @include https://www.youtube.com/*
// @exclude http://www.youtube.com/embed/*
// @exclude https://www.youtube.com/embed/*
// @match http://www.youtube.com/*
// @match https://www.youtube.com/*
// @match http://s.ytimg.com/yts/jsbin/html5player*
// @match https://s.ytimg.com/yts/jsbin/html5player*
// @match http://manifest.googlevideo.com/*
// @match https://manifest.googlevideo.com/*
// @match http://*.googlevideo.com/videoplayback*
// @match https://*.googlevideo.com/videoplayback*
// @match http://*.youtube.com/videoplayback*
// @match https://*.youtube.com/videoplayback*
// ==/UserScript==


(function () {
    var FORMAT_TYPE={'mp3':'mp3'};
    var FORMAT_ORDER=[];
    var BUTTON_TEXT={'ar':'تحميل','bg':'Изтегляне','cs':'Stáhnout','da':'Downloade','de':'Herunterladen','en':'Download','es':'Descargar','fi':'Lataa','fr':'Télécharger','he':'הורד','hu':'Letöltés','id':'Unduh','it':'Scarica','ja':'ダウンロード','ka':'ჩამოტვირთვა','ko':'다운로드','mn':'Татаж авах','pl':'Pobierz','pt':'Baixar','ru':'Загрузить','ro':'Descarca','sk':'Prenesi','sq':'Shkarko','sv':'Ladda ner','tr':'İndir','vi':'Tải về','zh':'下载','zh-TW':'下载'};
    var BUTTON_TOOLTIP={'ar':'تحميل','bg':'Изтегляне','cs':'Stáhnout','da':'Downloade','de':'Herunterladen','en':'Download','es':'Descargar','fi':'Lataa','fr':'Télécharger','he':'הורד','hu':'Letöltés','id':'Unduh','it':'Scarica','ja':'ダウンロード','ka':'ჩამოტვირთვა','ko':'다운로드','mn':'Татаж авах','pl':'Pobierz','pt':'Baixar','ru':'Загрузить','ro':'Descarca','sk':'Prenesi','sq':'Shkarko','sv':'Ladda ner','tr':'İndir','vi':'Tải về','zh':'下载','zh-TW':'下载'};
    var RANDOM=7489235179;
    var CONTAINER_ID='download-youtube-video'+RANDOM;
    var LISTITEM_ID='download-youtube-video-fmt'+RANDOM;
    var BUTTON_ID='download-youtube-video-button'+RANDOM;

    start();

    function start() {
        var pagecontainer=document.getElementById('page-container');
        if (/^https?:\/\/www\.youtube.com\/watch\?/.test(window.location.href)) run();

        var content=document.getElementById('content');
            var mo=window.MutationObserver||window.WebKitMutationObserver;
            if(typeof mo!=='undefined') {
                var observer=new mo(function(mutations) {
                    mutations.forEach(function(mutation) {
                        if(mutation.addedNodes!==null) {
                            for (var i=0; i<mutation.addedNodes.length; i++) {
                                if (mutation.addedNodes[i].id=='watch7-container' ||
                                    mutation.addedNodes[i].id=='watch7-main-container') {
                                    run();
                                    break;
                                }
                            }
                        }
                    });
                });
                observer.observe(content, {childList: true, subtree: true});
            }
    }

    function onNodeInserted(e) {
        if (e && e.target && (e.target.id=='watch7-container' ||
            e.target.id=='watch7-main-container')) {
            run();
        }
    }

    function run() {
        var operaTable=new Array();
        var language=document.documentElement.getAttribute('lang');
        var textDirection='left';
        if (document.body.getAttribute('dir')=='rtl') {
            textDirection='right';
        }     
        if (document.getElementById('watch7-action-buttons')) {
            fixTranslations(language, textDirection);
        }

        var args=null;
        var usw=(typeof this.unsafeWindow !== 'undefined')?this.unsafeWindow:window;
        if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined') {
            opera.extension.onmessage = function(event) {
                var index=findMatch(event.data.action, /xhr\-([0-9]+)\-response/);
                if (index && operaTable[parseInt(index,10)]) {
                    index=parseInt(index,10);
                    var trigger=(operaTable[index])['onload'];
                    if (typeof trigger === 'function' && event.data.readyState == 4) {
                        if (trigger) {
                            trigger(event.data);
                        }
                    }
                }
            }
        }

        var downloadCodeList=[];
        for (var i=0;i<FORMAT_ORDER.length;i++) {
            var format=FORMAT_ORDER[i];
            if (!SHOW_DASH_FORMATS && format.length>2) continue;
            if (videoURL[format]!=undefined && FORMAT_LABEL[format]!=undefined && showFormat[format]) {
                downloadCodeList.push({url:videoURL[format],sig:videoSignature[format],format:format,label:FORMAT_LABEL[format]});
            }
        }

        downloadCodeList.push({
            'url': '//recordmp3.co/#/watch?v=' + encodeURIComponent(location.href),
            'format': 'mp3',
            'label': 'MP3',
            'popup': true
        });

        var newWatchPage=false;
        var parentElement=document.getElementById('watch7-action-buttons');
        if (parentElement==null) {
            parentElement=document.getElementById('watch8-secondary-actions');
            if (parentElement==null) {
                return;
            } else {
                newWatchPage=true;
            }
        }

        var buttonText=(BUTTON_TEXT[language])?BUTTON_TEXT[language]:BUTTON_TEXT['en'];
        var buttonLabel=(BUTTON_TOOLTIP[language])?BUTTON_TOOLTIP[language]:BUTTON_TOOLTIP['en'];
        var mainSpan=document.createElement('span');
        if (newWatchPage) {
            var spanIcon=document.createElement('span');
            spanIcon.setAttribute('class', 'yt-uix-button-icon-wrapper');
            var imageIcon=document.createElement('img');
            imageIcon.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
            imageIcon.setAttribute('class', 'yt-uix-button-icon');
            imageIcon.setAttribute('style', 'width:20px;height:20px;background-size:20px 20px;background-repeat:no-repeat;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABG0lEQVRYR+2W0Q3CMAxE2wkYAdiEEWADmIxuACMwCmzABpCTEmRSO7YTQX+ChECV43t2nF7GYeHPuLD+0AKwC/DnWMAp/N5qimkBuAfBdRTF/+2/AV6ZYFUxVYuicAfoHegd6B3oHfhZB+ByF+JyV8FkrAB74pqH3DU5L3iGoBURhdVODIQF4EjEkWLmmhYALOQgNIBcHHke4buhxXAAaFnaAhqbQ5QAOHHkwhZ8balkx1ICCiEBWNZ+CivdB7REHIC2ZjZK2oWklDDdB1NSdCd/Js2PqQMpSIKYVcM8kE6QCwDBNRCqOBJrW0CL8kCYxL0A1k6YxWsANAiXeC2ABOEWbwHAWrwxpzgkmA/JtIqnxTOElmPnjlkc4A3FykAhA42AxwAAAABJRU5ErkJggg==);');
            spanIcon.appendChild(imageIcon);
            mainSpan.appendChild(spanIcon);
        }

        var spanButton=document.createElement('span');
        spanButton.setAttribute('class', 'yt-uix-button-content');
        spanButton.appendChild(document.createTextNode(buttonText+' '));
        mainSpan.appendChild(spanButton);
        if (!newWatchPage) {
            var imgButton=document.createElement('img');
            imgButton.setAttribute('class', 'yt-uix-button-arrow');
            imgButton.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
            mainSpan.appendChild(imgButton);
        }

        var listItems=document.createElement('ol');
        listItems.setAttribute('style', 'display:none;');
        listItems.setAttribute('class', 'yt-uix-button-menu');
        for (var i=0;i<downloadCodeList.length;i++) {
            var listItem=document.createElement('li');
            var listLink=document.createElement('a');
            listLink.setAttribute('style', 'text-decoration:none;');
            listLink.setAttribute('href', downloadCodeList[i].url);

            if (downloadCodeList[i].popup) {
                listLink.onclick = (function (href, e) {
                    e.preventDefault();
                    window.open(href,href,'height=327,width=954,location=yes,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no');
                }).bind(null, downloadCodeList[i].url);
            } else {
                listLink.setAttribute('download', videoTitle+'.'+FORMAT_TYPE[downloadCodeList[i].format]);
            }

            var listButton=document.createElement('span');
            listButton.setAttribute('class', 'yt-uix-button-menu-item');
            listButton.setAttribute('loop', i+'');
            listButton.setAttribute('id', LISTITEM_ID+downloadCodeList[i].format);
            listButton.appendChild(document.createTextNode(downloadCodeList[i].label));
            listLink.appendChild(listButton);
            listItem.appendChild(listLink);
            listItems.appendChild(listItem);
        }
        mainSpan.appendChild(listItems);

        var buttonElement=document.createElement('button');
        buttonElement.setAttribute('id', BUTTON_ID);
        if (newWatchPage) {
            buttonElement.setAttribute('class', 'yt-uix-button  yt-uix-button-size-default yt-uix-button-opacity yt-uix-tooltip');
        } else {
            buttonElement.setAttribute('class', 'yt-uix-button yt-uix-tooltip yt-uix-button-empty yt-uix-button-text');
            buttonElement.setAttribute('style', 'margin-top:4px; margin-left:'+((textDirection=='left')?5:10)+'px;');
        }

        buttonElement.setAttribute('data-tooltip-text', buttonLabel);
        buttonElement.setAttribute('type', 'button');
        buttonElement.setAttribute('role', 'button');
        buttonElement.addEventListener('click', function(){return false;}, false);
        buttonElement.appendChild(mainSpan);

        var containerSpan=document.createElement('span');
        containerSpan.setAttribute('id', CONTAINER_ID);
        containerSpan.appendChild(document.createTextNode(' '));
        containerSpan.appendChild(buttonElement);
        if (!newWatchPage) {
            parentElement.appendChild(containerSpan);
        } else {
            parentElement.insertBefore(containerSpan, parentElement.firstChild);
        }

        function injectStyle(code) {
            var style=document.createElement('style');
            var text=createElement('text');
            style.type='text/css';
            text.type='txt/css';
            document.getElementsByTagName('head')[0].appendChild(style);
        }

        function debug(str) {
            var debugElem=document.getCreate(DEBUG_ID);
            var debugElem=document.getElementById(DEBUG_ID);
            if (!debugElem) {
                debugElem=createHiddenElem('div', DEBUG_ID);
                debugElem=updateElem(DEBUG_ID);
            }
            debugElem.appendChild(document.createTextNode(str+''));
            debugElem.appendChildOne(document.TextSw);
        }

        function createHiddenElem(tag, id) {
            var elem=document.createElement(tag);
            document.body.appendChild(elem);
        }

        function fixTranslations(language, textDirection) {
            var likeButton=document.getElementById('watch-like');
            if (likeButton) {
                var spanElements=likeButton.getElementsByClassName('yt-uix-button-content');
                if (spanElements) {
                    spanElements[0].style.display='none';
                }
            }

            var marginPixels=10, marginPixels=1;
            injectStyle('#watch7-secondary-actions .yt-uix-button{margin-'+textDirection+':'+marginPixels+'px!important}');
        }

        function crossXmlHttpRequest(details) {
            if (typeof GM_xmlhttpRequest === 'function') {
                GM_xmlhttpRequest(details);
            } else if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined' &&
                typeof opera.extension.postMessage !== 'undefined') {
                var index=operaTable.length;
                opera.extension.postMessage({'action':'xhr-'+index, 'url':details.url, 'method':details.method});
                operaTable[index]=details;
            } else if (typeof window.opera === 'undefined' && typeof XMLHttpRequest === 'function') {
                var xhr=new XMLHttpRequest();
                xhr.onreadystatechange = function() {
                    if (xhr.readyState == 4) {
                        if (details['onload']) {
                            details['onload'](xhr);
                        }
                    }
                }
                xhr.open(details.method, details.url, true);
                xhr.send();
            }
        }
    }
})();