Greasy Fork

Greasy Fork is available in English.

Disney+ Audio Downloader

Download audio from Disney+

当前为 2020-06-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name           Disney+ Audio Downloader
// @name:fr        Disney+ Audio Downloader
// @namespace      http://greasyfork.icu/fr/users/572942-stegner
// @homepage       http://greasyfork.icu/fr/scripts/405994-disney-audio-downloader
// @description    Download audio from Disney+
// @description:fr Télécharger l'audio de Disney+
// @version        1.0
// @author         stegner
// @match          https://www.disneyplus.com/*
// @grant          none
// ==/UserScript==

function start(){
	if (typeof document.initaudio !== "undefined") {
		document.initaudio();
	}
	if (typeof document.initsub !== "undefined") {
		document.initsub();
	}
	listensend();
    document.handleinterval = setInterval(buttonhandle,100);
}

window.onload = start;

document.initaudio = function(){
    document.audios = new Array();
	document.content = new Uint8Array();
	document.baseurl="";
	document.m3u8found=false;
	document.wait=false;
    document.filename="";
    document.episode="";
    document.audioid=null;

    // Add download icon
    document.styleSheets[0].addRule('#audioTrackPicker > div:before','content:"";color:#fff;padding-right:35px;padding-top:2px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAIGNIUk0AAHonAACAgwAA+mQAAIDSAAB2hgAA7OkAADmeAAAV/sZ+0zoAAAE4SURBVHja1JS7LkRRFIa/M6aYRCEuCUEUgihFBolGVGqiFY1ConfpNB7CiygUGm8hOiMukwiCCMl8mj2xc5yZM8M0/mTlrLP2v75zydo7UclRL3AGlIAl4L6ZuUC+5oEZYBoo55lbAdai/LPTwFongG3pfwI3gZ3ovhjlXVG+BWz/6FbjKPuto1CbjWoLobYf1RZjRho4pt5F5g11QK2F6FFXo/UXdbwZEHVQvY2aztWPECdR/TkNawREHUpB03pSJ7J6Cf9gL3xOvDiiXmfAHtSplLek7qorqI/BeJjxxFG1kgNDPQjrn4VoLPozRqgCzAGXwFXILzJ8w+H6XgRegW7grcGs3gCTOfP8UgfGg139wwapxrugDl0H+oCkTZjAcsiTxBaO7HZUBI6BtfCmv4Un4aw8/RoA7wq6AO4uOhAAAAAASUVORK5CYII=) no-repeat right;width:20px;height:18px;position:absolute;top:6px;right:10px;opacity:0.6;cursor:pointer;');
    document.styleSheets[0].addRule('#audioTrackPicker > div:hover:before','opacity:1;');
}

// Catch M3U8 files
function listensend(){
    XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send;

    var newSend = function(vData) {
        if(!document.m3u8found) {
            try {
                var objData = JSON.parse(vData);
                if(typeof objData.url !== 'undefined') {
                    if(objData.url.indexOf(".m3u8")>0 && document.url!=objData.url) {
                        // m3u8 url
                        document.url = objData.url;
                        document.langs = [];
                        document.baseurl=document.url.substring(0,document.url.lastIndexOf('/')+1);
                        document.m3u8found=true;
                        getpagecontent(m3u8loaded,document.url);
                    }
                }
            } catch (error) {}
        }
        this.realSend(vData);
    }

    XMLHttpRequest.prototype.send = newSend;
}

function m3u8loaded(response) {
	if (typeof document.m3u8sub !== "undefined") {
        document.m3u8sub(response);
    }
    if (typeof document.m3u8audio !== "undefined") {
        document.m3u8audio(response);
    }
    document.wait=false;
}

document.m3u8audio = function(response){

	var lines = response.split('#');
    var found = false;
	if(lines[2].indexOf("EXT-X-INDEPENDENT-SEGMENTS")==0){
		// Audio tracks list
		var quality=null;
		lines.forEach(function(line) {
	        if(line.indexOf('TYPE=AUDIO')>0) {
	            // audio infos
	            if(line.indexOf('GROUP-ID="eac-3"')>0 && (quality==null||quality=="eac-3")){
	            	quality="eac-3";
	            	document.audios.push(linetoarray(line));
	            }
	            else if(line.indexOf('GROUP-ID="aac-128k"')>0 && (quality==null||quality=="aac-128k")){
	            	quality="aac-128k";
	            	document.audios.push(linetoarray(line));
	            }
	            else if(line.indexOf('GROUP-ID="aac-64k"')>0 && (quality==null||quality=="aac-64k")){
	            	quality="aac-64k";
	            	document.audios.push(linetoarray(line));
	            }
	        }
	    });
	}
	else if(response.indexOf(".mp4a")>0) {
		//console.log(lines);
		downloadmp4a(response);
	}
    
}

function downloadmp4a(m3u8data){
	var lines = m3u8data.split(/\r?\n/g);
	var mapfound=false;
	var percent;
	var i=0;
	document.downloadInterval = setInterval(function () {
		var line = lines[i];
		var url=null;
		if(line!=null){
            var uri = document.audios[document.audioid].URI;
			if(line.indexOf("map.mp4a")>0 && !mapfound){
				// Get mp4a map
				url = document.baseurl+uri.substring(0,uri.lastIndexOf("/")+1)+line.substring(line.indexOf('"')+1,line.lastIndexOf('"'));
				mapfound=true;
			}
			else if(line.indexOf("_000.mp4a")>0 && line.indexOf("DUB_CARD")<0){
				// Get mp4a data
				url = document.baseurl+uri.substring(0,uri.lastIndexOf("/")+1)+line;
			}

			if(url!=null && !document.wait){
				// Download file
				getpagecontent(mp4aloaded,url,true);
				document.wait=true;
				i++;
			}
			else if(url==null){
				// Skip line
				i++;
			}

			if(percent!=Math.round((i/lines.length)*100)){
				percent=Math.round((i/lines.length)*100);
				document.styleSheets[0].addRule('#audioTrackPicker > div:nth-child('+(document.audioid+1)+'):before','content:"'+percent+'%";');
			}
		}
		else {
			// Download finished
			clearInterval(document.downloadInterval);
			document.styleSheets[0].addRule('#audioTrackPicker > div:nth-child('+(document.audioid+1)+'):before','content:"";');
			exportblob(document.content, 'video/mp4');
			document.content=new Uint8Array();
		}
	},10);
}


function mp4aloaded(response) {
	document.content=appendbuffer(document.content,response);
	document.wait=false;
}

function linetoarray(line) {
    var result = new Array();
    var values = line.split(',');
    values.forEach(function(value) {
        var data = value.replace(/\r\n|\r|\n/g,'').split('=');
        if(data.length>1) {
            var key = data[0];
            var content = data[1].replace(/"/g,'');
            result[key]=content;
        }
    });
    return result;
}

function buttonhandle() {
    var buttons = document.getElementsByClassName("control-icon-btn");
    if(buttons.length>0) {
        if (typeof document.clickhandlesub !== "undefined") {
            document.clickhandlesub();
        }
        if (typeof document.clickhandleaudio !== "undefined") {
            document.clickhandleaudio();
        }

        document.filename = document.getElementsByClassName("title-field")[0].innerText;
	    if(document.getElementsByClassName("subtitle-field").length>0) {
	        document.episode = document.getElementsByClassName("subtitle-field")[0].innerText
	    }
    }

    if(document.oldlocation!=window.location.href&&document.oldlocation!=null) {
        // location changed
        document.m3u8found=false;
        document.audios = [];
        document.langs = [];
    }

    document.oldlocation=window.location.href;
}

document.clickhandleaudio = function() {
    var picker = document.getElementsByClassName("options-picker audio-track-picker");
    picker[0].childNodes.forEach(function(child) {
        var element = child.childNodes[0];
        var lang = element.childNodes[1].innerHTML;
        if(child.onclick==null) {
            child.onclick = selectaudio;
        }
    });
}

function selectaudio(e) {
    var width = this.offsetWidth;
    // Check click position
    if(e.layerX>=width-30&&e.layerX<=width-10&&e.layerY>=5&&e.layerY<=25){
        // Download sub
        download(this.childNodes[0].childNodes[1].innerHTML);
        // Cancel selection
        return false;
    }
}

function download(langname) {
    if(!document.wait){
    	var count=0;
        document.audios.forEach(function(audio) {
            if(audio.NAME==langname) {
                document.audioid=count;
                getpagecontent(m3u8loaded,document.baseurl+audio.URI);
                document.wait=true;
            }
            count++;
        });
        if(count==0){
            alert("An error has occurred, please reload the page.");
        }
    }
    
}

function getpagecontent(callback,url,binary) {
	var http=new XMLHttpRequest();
	http.open("GET", url, true);
	if(binary){
		http.responseType = "arraybuffer";
	}
	http.onloadend = function() {
		if(http.readyState == 4 && http.status == 200) {
			if(binary){
				callback(http.response);
			}
			else {
				callback(http.responseText);
			}
		}
		else if (http.status === 404) {
			callback("");
		}
	}
	http.send();
}

function appendbuffer(buffer1, buffer2) {
	var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
	tmp.set(new Uint8Array(buffer1), 0);
	tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
	return tmp;
};

// Save file as arraybuffer
function exportblob(data, mimeType) {
	var blob, url;
	var output = document.filename;
    if(document.episode!="") {
        output+= " - "+document.episode.replace(':','');
    }
    output += "."+document.audios[document.audioid].LANGUAGE;
    output += ".mp4";


	blob = new Blob([data], {
		type: mimeType
	});
	url = window.URL.createObjectURL(blob);
	downloadurl(url, output);
	setTimeout(function() {
		return window.URL.revokeObjectURL(url);
	}, 1000);
};

function downloadurl(data, fileName) {
	var a;
	a = document.createElement('a');
	a.href = data;
	a.download = fileName;
	document.body.appendChild(a);
	a.style = 'display: none';
	a.click();
	a.remove();
};