Greasy Fork is available in English.

Download Youtube videos and subtitles

获取youtube视频和字幕的下载链接

Version au 2017-09-02 01:23:58 UTC. Voir la dernière version.

// ==UserScript==
// @name      Download Youtube videos and subtitles
// @namespace  https://www.findhao.net
// @version    0.2.8
// @description  获取youtube视频和字幕的下载链接
// @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*
// @copyright  2017+, Find
// @author FindHao
// ==/UserScript==

(function () {
    var BUTTON_TEXT = { 'ar': 'تنزيل', 'cs': 'Stáhnout', 'de': 'Herunterladen', 'en': 'Download', 'es': 'Descargar', 'fr': 'Télécharger', 'hi': 'डाउनलोड', 'hu': 'Letöltés', 'id': 'Unduh', 'it': 'Scarica', 'ja': 'ダウンロード', 'ko': '내려받기', 'pl': 'Pobierz', 'pt': 'Baixar', 'ro': 'Descărcați', 'ru': 'Скачать', 'tr': 'İndir', 'zh': '下载', 'zh-TW': '下載' };
    var BUTTON_TOOLTIP = { 'ar': 'تنزيل هذا الفيديو', 'cs': 'Stáhnout toto video', 'de': 'Dieses Video herunterladen', 'en': 'Download this video', 'es': 'Descargar este vídeo', 'fr': 'Télécharger cette vidéo', 'hi': 'वीडियो डाउनलोड करें', 'hu': 'Videó letöltése', 'id': 'Unduh video ini', 'it': 'Scarica questo video', 'ja': 'このビデオをダウンロードする', 'ko': '이 비디오를 내려받기', 'pl': 'Pobierz plik wideo', 'pt': 'Baixar este vídeo', 'ro': 'Descărcați acest videoclip', 'ru': 'Скачать это видео', 'tr': 'Bu videoyu indir', 'zh': '下载此视频', 'zh-TW': '下載此影片' };
    var RANDOM = 7489235179; // Math.floor(Math.random()*1234567890);
    var CONTAINER_ID = 'download-youtube-video' + RANDOM;

    start();
    function start() {
        function isMaterial() {
            var temp;
            temp = document.querySelector("ytd-app, [src*='polymer'],link[href*='polymer']");
            if (temp && !document.getElementById("material-notice")) {
                temp = document.createElement("template");
                temp.innerHTML = //
                `<div id='material-notice' style='border-radius:2px;color:#FFF;padding:10px;background-color:#ff0000;box-shadow:0 0 3px rgba(0,0,0,.5);font-size:12px;position:fixed;bottom:20px;right:50px;z-index:99999'>
<strong><ins>WARNING : </ins></strong>'FindYoutube.net' is not compatible with the experimental YouTube Material Layout<br/> which is under BETA testing.<br><br>
<a href='https://www.findyoutube.net/fix' target='_blank' style='color:#FFF;font-weight:bold;'>Click here</a> for instructions on how to continue using the video downloading features.<br>This addon will get migrated to the new layout if Youtube makes the BETA design as default.<br>
<strong><ins>WARNING : </ins></strong>Findyoutube.net暂时不支持测试版的youtube界面,<a href='https://www.findyoutube.net/fix' target='_blank' style='color:#FFF;font-weight:bold;'>请按此处示意</a>切换回经典界面。
</div>`;
                document.documentElement.appendChild(temp.content.firstChild);
                document.documentElement.removeAttribute("data-user_settings");
                return true;
            }
        }
        isMaterial();
        var pagecontainer = document.getElementById('page-container');
        if (!pagecontainer) return;
        if (/^https?:\/\/www\.youtube.com\/watch\?/.test(window.location.href)) run();
        var isAjax = /class[\w\s"'-=]+spf\-link/.test(pagecontainer.innerHTML);
        var logocontainer = document.getElementById('logo-container');
        if (logocontainer && !isAjax) { // fix for blocked videos
            isAjax = (' ' + logocontainer.className + ' ').indexOf(' spf-link ') >= 0;
        }
        var content = document.getElementById('content');
        if (isAjax && content) { // Ajax UI
            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-main-container') { // || id=='watch7-container'
                                    run();
                                    break;
                                }
                            }
                        }
                    });
                });
                observer.observe(content, { childList: true, subtree: true }); // old value: pagecontainer
            } else { // MutationObserver fallback for old browsers
                pagecontainer.addEventListener('DOMNodeInserted', onNodeInserted, false);
            }
        }
    }

    function run() {
        var args = null;
        var usw = (typeof this.unsafeWindow !== 'undefined') ? this.unsafeWindow : window; // Firefox, Opera<15
        if (usw.ytplayer && usw.ytplayer.config && usw.ytplayer.config.args) {
            args = usw.ytplayer.config.args;
        }
        var videoID = null;
        if (args) {
            videoID = args['video_id'];
        }
        var language = document.documentElement.getAttribute('lang');
        // find parent container
        var newWatchPage = false;
        var parentElement = document.getElementById('top-level-buttons');
        if (parentElement == null) {
            parentElement = document.getElementById('top-level-buttons');
            if (parentElement == null) {
                console.log('DYVAM Error - No container for adding the download button. YouTube must have changed the code.');
                return;
            } else {
                newWatchPage = true;
            }
        }
        // get button labels
        var buttonText = (BUTTON_TEXT[language]) ? BUTTON_TEXT[language] : BUTTON_TEXT['en'];
        var buttonLabel = (BUTTON_TOOLTIP[language]) ? BUTTON_TOOLTIP[language] : BUTTON_TOOLTIP['en'];

        // generate download code for regular interface
        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) { // old UI
            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');
        // mainSpan.appendChild(listItems);
        var buttonElement = document.createElement('button');
        if (newWatchPage) {
            buttonElement.setAttribute('class', 'yt-uix-button  yt-uix-button-size-default yt-uix-button-opacity yt-uix-tooltip');
        } else { // old UI
            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:' + 5 + 'px;');
        }
        buttonElement.setAttribute('type', 'button');
        buttonElement.setAttribute('role', 'button');
        var form1 = document.createElement("form");
        form1.id = "post";
        form1.name = "post";
        form1.method = "post";
        form1.target = "_blank";
        form1.action = "http://www.findyoutube.net/";
        var input = document.createElement("input");
        input.type = "hidden";
        input.name = "url";
        input.value = window.location.href;

        form1.appendChild(input);

        buttonElement.addEventListener("click", function () {
            form1.submit();
        });
        // 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);
        document.body.appendChild(form1);

        // add the button
        if (!newWatchPage) { // watch7
            parentElement.appendChild(containerSpan);
        } else { // watch8
            parentElement.insertBefore(containerSpan, parentElement.firstChild);
        }
    }

})();