Youtube downloader for NoScript

This script is no longer maintained, please use https://greasyfork.org/en/scripts/1317-download-youtube-videos-as-mp4

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name           Youtube downloader for NoScript
// @include        http://*.youtube.com/watch*
// @include        http://youtube.com/watch*
// @include        https://*.youtube.com/watch*
// @include        https://youtube.com/watch*
// @run-at         document-end
// @description    This script is no longer maintained, please use https://greasyfork.org/en/scripts/1317-download-youtube-videos-as-mp4
// @version 0.0.1.20170330045620
// @namespace https://greasyfork.org/users/10916
// ==/UserScript==

var nasp, spec, fmtvar, titlevar, newa2 = "", scrhead = document.getElementsByTagName("script");

var formats = {
	5:  { itag: 5, quality: 5, description: "Low Quality, 240p", format: "FLV", fres: "240p", 	mres: { width:  400, height:  240 }, acodec: "MP3", vcodec: "SVQ"},
	17: { itag: 17, quality: 4, description: "Low Quality, 144p", format: "3GP", fres: "144p", mres: { width:  0, height: 0  }, acodec: "AAC", vcodec: ""},
	18: { itag: 18, quality: 15, description: "Low Definition, 360p", format: "MP4", fres: "360p", mres: { width:  480, height:  360 }, acodec: "AAC", vcodec: "H.264"},
	22: { itag: 22, quality: 35, description: "High Definition, 720p", format: "MP4", fres: "720p",	mres: { width: 1280, height:  720 }, acodec: "AAC", vcodec: "H.264"},
	34: { itag: 34, quality: 10, description: "Low Definition, 360p", format: "FLV", fres: "360p", 	mres: { width:  640, height:  360 }, acodec: "AAC", vcodec: "H.264"},
	35: { itag: 35, quality: 25, description: "Standard Definition, 480p", format: "FLV" , fres: "480p", mres: { width:  854, height:  480 }, acodec: "AAC", vcodec: "H.264"},
	36: { itag: 36, quality: 6, description: "Low Quality, 240p", format: "3GP", fres: "240p", 	mres: { width:  0, height:  0 }, acodec: "AAC", vcodec: ""},
	37: { itag: 37, quality: 45, description: "Full High Definition, 1080p", format: "MP4", fres: "1080p", mres: {width: 1920, height: 1080}, acodec: "AAC", vcodec: "H.264"},
	38: { itag: 38, quality: 55, description: "Original Definition", format: "MP4" , fres: "Orig",	mres: { width: 4096, height: 3072 }, acodec: "AAC", vcodec: "H.264"},
	43: { itag: 43, quality: 20, description: "Low Definition, 360p", format: "WebM", fres: "360p",	mres: { width:  640, height:  360 }, acodec: "Vorbis", vcodec: "VP8"},
	44: { itag: 44, quality: 30, description: "Standard Definition, 480p", format: "WebM", fres: "480p", mres: { width:  854, height:  480 }, acodec: "Vorbis", vcodec: "VP8"},
	45: { itag: 45, quality: 40, description: "High Definition, 720p", format: "WebM", fres: "720p", mres: { width: 1280, height:  720 }, acodec: "Vorbis", vcodec: "VP8"},
	46: { itag: 46, quality: 50, description: "Full High Definition, 1080p", format: "WebM", fres: "1080p",	mres: {width: 1280, height: 720}, acodec: "Vorbis", vcodec: "VP8"},
	82: { itag: 82, quality: 16, description: "Low Definition 3D, 360p", format: "MP4",  fres: "360p", mres: { width: 640,  height:  360 }, acodec: "AAC", vcodec: "H.264"},
	84: { itag: 84, quality: 41, description: "High Definition 3D, 720p", format: "MP4",  fres: "720p",	mres: { width: 1280, height:  720 }, acodec: "AAC", vcodec: "H.264"},
	100: { itag: 100, quality: 17, description: "Low Definition 3D, 360p", format: "WebM", fres: "360p", mres: { width: 640,  height:  360 }, acodec: "Vorbis", vcodec: "VP8"},
	102: { itag: 102, quality: 42, description: "High Definition 3D, 720p", format: "WebM", fres: "720p", mres: {width: 1280, height: 720}, acodec: "Vorbis", vcodec: "VP8"},
	133: { itag: 133, description: "", format: "MP4", fres: "240p", acodec: "noaudio", vcodec: "H.264"},
	134: { itag: 134,  description: "", format: "MP4", fres: "360p", acodec: "noaudio", vcodec: "H.264"},
	135: { itag: 135, description: "MP4 480p - no audio", format: "MP4", fres: "480p", acodec: "noaudio", vcodec: "H.264"},
	136: { itag: 136,  description: "MP4 720p", format: "MP4", fres: "720p", acodec: "noaudio", vcodec: "H.264"},
	137: { itag: 137, description: "MP4 1080p - no audio", format: "MP4", fres: "1080p", acodec: "noaudio", vcodec: "H.264"},
	138: { itag: 138, description: "MP4 2160p - no audio", format: "MP4", fres: "2160p", acodec: "noaudio", vcodec: "H.264"},
	140: { itag: 140, description: "M4A 128kbps - audio", format: "m4a", fres: "128k", acodec: "AAC", vcodec: "novideo"},
	141: { itag: 141, description: "M4A 256kbps - audio", format: "m4a", fres: "256k", acodec: "AAC", vcodec: "novideo"},
    160: { itag: 160, description: "", format: "MP4",  acodec: "noaudio", fres: "144p", vcodec: "H.264/15fps"},
	264: { itag: 264, description: "MP4 1440p - no audio", format: "MP4", fres: "1440p",  acodec: "noaudio", vcodec: ""},
	298: { itag: 298, description: "MP4 720p 60fps - no audio", format: "MP4", fres: "720p",  acodec: "noaudio", vcodec: "H.264/60fps"},
	299: { itag: 299, description: "MP4 1080p 60fps - no audio", format: "MP4", fres: "1080p",  acodec: "noaudio", vcodec: "H.264/60fps"}
	}
	
	
	
var wclh = (window.content||window).location.href.toString();
var html = "";

if (document.getElementById("eow-title")) {
	titlevar = parseTV(document.getElementById("eow-title").textContent.toString());
} else if (document.getElementById("watch-headline-title")&&document.getElementById("watch-headline-title").childNodes[1].innerHTML.toString()) {
	titlevar = parseTV(document.getElementById("watch-headline-title").childNodes[1].textContent.toString());
} else {
	titlevar = "Download_Video_Link";
}
	
function addBox(strR) {
    var q = strR.split("itag=")[1].split("&")[0];
    var fmt = formats[q];
    if (fmt) {
        html = html + "<option value='"+strR+"&title="+titlevar+"'>" + fmt.format + " " + fmt.fres + " " +fmt.acodec + " " + fmt.vcodec + "</option>";
    }
}

function parseTV(h) {
	h = unescape(h);
	h = h.replace(/\W/g,"_").replace(/\_+/g,"_").replace("_amp_", "_and_");
	while (!h.charAt(0).match(/[a-zA-Z0-9]/i)&&h.length>1) {h = h.substr(1);}
	while (h.length>1&&!h.charAt(h.length-1).match(/[a-zA-Z0-9]/i)) {h = h.substring(0,h.length-1);}
	return(h);
}

function getSType(spec) {
	return formats[spec].quality;
}

function procURLS(nasp) {
	nasp = cleanArray(nasp);
	for (x=0;x<nasp.length;x++) {
		var newalink = unescape(nasp[x]);
		if (newalink.indexOf("http")==-1) { nasp.splice(x,1); }
	}
	for (x=0;x<nasp.length;x++) {
		var nchkend = "", nlink = "", nchk = "", ny = "", narray = new Array();
		nasp[x] = unescape(unescape(nasp[x]));
		narray = nasp[x].split("&");
		narray = cleanArray(narray);
		for (y=0;y<narray.length;y++) {
			ny = narray[y];
			if (ny!=null&&ny!=""&&ny.match(/url\=/i)!=-1&&ny.indexOf("?")!=-1) {
				nlink = unescape(ny.split("url=")[1]);
				narray.splice(y,1);
				break;
			}
			ny = ""; 
		}

		for (var nx=0; nx<narray.length; nx++) {
			if (narray[nx].split("=")) {
				nchk = narray[nx].split("=")[0];
				var specific = "";
				nchkend = narray[nx].indexOf("=");
				nchkend = narray[nx].substr(nchkend+1);
				//if (acceptargs.indexOf(nchk)!=-1 && nlink.indexOf("&"+nchk+"=")==-1 && nlink.indexOf("?"+nchk+"=")==-1) {  //for compatibility, no longer checking against accepted arguments
				if (nlink.indexOf("&"+nchk+"=")==-1 && nlink.indexOf("?"+nchk+"=")==-1) {
					if (nchk.match(/fallback_host$/i)) {
						var nrxp = new RegExp("^(http|https)\:\/\/.{0,}\.(com|net)","i");
						if (nlink.indexOf("videoplayback")==-1&&nlink.match(nrxp)) {
						}
					}
					else if (nchk.match(/signature$/i)) {
						nlink+="&signature=" + nchkend; 
					}
					else if (nchk.match(/sig$/i)&&nlink.indexOf("?signature=")==-1&&nlink.indexOf("&signature=")==-1) {
						nlink+="&signature=" + nchkend; 
					}
					else if (nchk.length==1&&nchk.match(/s$/i)&&nlink.indexOf("?signature=")&&nlink.indexOf("&signature=")==-1) {
						//alert(static_decrypt_signature(nchkend).length);
						nlink+="&signature=" + static_decrypt_signature(nchkend);
					}
					else if (nchk.match(/type$/i)||nchk.match(/quality$/i)) {
						nlink = nlink+"&"+nchk+"="+encodeURIComponent(nchkend);
					} else {
						nlink+="&"+nchk+"="+nchkend;
					}
				}
			}
		}
		if (nlink!=null&&nlink!="") {
			if (nlink.indexOf("requiressl")!=-1 && nlink.indexOf("requiressl=")==-1) {
				nlink+="&requiressl=yes";
			}
			addBox(decodeURIComponent(nlink));
		}
	}
}

function cleanArray(act){
	var newAr = new Array();
	for(var x = 0; x<act.length; x++){
		if (act[x]){
			newAr.push(act[x].toString());
		}
	}
	return newAr;
}

function cleanJSON(jsn) {
	if (jsn.charAt(0)!="{") {jsn = jsn.substring(jsn.indexOf('{'));}
	while (jsn.charAt(jsn.length-1).match(/\s/)) {jsn = jsn.substring(0,jsn.length-2);}
	if (jsn.indexOf("},")!=-1) {jsn = jsn.split('},')[0] + '}'}
	try {var jda = eval(JSON.parse(jsn))}
		catch(err) {
		while (!jsn.charAt(jsn.length-1).match(/\}/)) {jsn = jsn.substring(0,jsn.length-2);}
		var jda = eval(JSON.parse(jsn));
	}
	return jda;
}

function runIt(a1) {
	for (var b3=0; b3<a1.length; b3++) {
		if (a1[b3].innerHTML.match(/yt.playerConfig\ \=/gi)||a1[b3].innerHTML.match(/ytplayer.config\ \=/gi)) {
			var jsn = a1[b3].innerHTML.toString();
			if (jsn.match(/ytplayer.config\ \=/gmi)) {
				jsn = jsn.split('ytplayer.config\ =')[1];
				jsnaf = '{"adaptive_fmts' + jsn.split("adaptive_fmts")[1];
				jsnsm = '{"url_encoded_fmt_stream_map' + jsn.split("url_encoded_fmt_stream_map")[1];
			}
			var dat ="";
			jdata = cleanJSON(jsnsm);
			try { var dat = jdata.args.url_encoded_fmt_stream_map }
			catch(err) {try { var dat = jdata.url_encoded_fmt_stream_map } catch(err){}}
			dat = dat.replace(/\"/g,"\%22").replace(/\,\+/g,"%2C%2B");
			if (dat.indexOf(",")!=-1) {dat = dat.split(",")}
			procURLS(dat);
			
			var dat ="";
			jdata = cleanJSON(jsnaf);
			try { var dat = jdata.args.adaptive_fmts }
			catch(err) {try { var dat = jdata.adaptive_fmts } catch(err){}}
			
			dat = dat.replace(/\"/g,"\%22").replace(/\,\+/g,"%2C%2B");
			if (dat.indexOf(",")!=-1) {dat = dat.split(",")}
			procURLS(dat);
		}
	}
}

function setCook() {
	if (window.navigator.cookieEnabled) {
		document.cookie = "GEO=;domain=.youtube.com;path=/"; 
		//document.cookie = "use_hitbox=;"; 
		document.cookie = "VISITOR_INFO1_LIVE=;domain=.youtube.com;path=/"; 
		//document.cookie = "recently_watched_video_id_list=;"
		document.cookie = "YSC=;domain=.youtube.com;path=/";
	}
}

function reverse(s){
    return s.split("").reverse().join("");
}

function static_decrypt_signature(s, age_gate) {
	if (age_gate) {
		if (s.length==86) {
		//	return s[2:63] + s[82] + s[64:82] + s[63];
		return s.substring(2,63) + s.substr(82,1) + s.substring(64,82) + s.substr(63,1);
		}
	}
	if (s.length==93) {
		s = reverse(s);
		//return s[86:29:-1] + s[88] + s[28:5:-1];
		return s.substring(7,64) + s.substr(5,1) + s.substring(65,88);
	} else if(s.length==92) {
	//	return s[25] + s[3:25] + s[0] + s[26:42] + s[79] + s[43:79] + s[91] + s[80:83];
		return s.substr(25,1) + s.substring(3,25) + s.substr(0,1) + s.substring(26,42) + s.substr(79,1) + s.substring(43,79) + s.substr(91,1) + s.substring(80,83);
	} else if(s.length==91) {
		s = reverse(s);
	//return s;
	//	return s[84:27:-1] + s[86] + s[26:5:-1];
		return s.substring(7,64) + s.substr(5,1) + s.substring(65,86);
	} else if(s.length==90) {
	//	return s[25] + s[3:25] + s[2] + s[26:40] + s[77] + s[41:77] + s[89] + s[78:81];
		return s.substr(25,1) + s.substring(3,25) + s.substr(2,1) + s.substring(26,40) + s.substr(77,1) + s.substring(41,77) + s.substr(89,1) + s.substring(78,81);
	} else if(s.length==89) {
		s = reverse(s);
	//	return s[84:78:-1] + s[87] + s[77:60:-1] + s[0] + s[59:3:-1];
		return s.substring(5,11) + s.substr(2,1) + s.substring(12,29) + s.substr(89,1) + s.substring(30,86);
	} else if(s.length==88) {
	//	return s[7:28] + s[87] + s[29:45] + s[55] + s[46:55] + s[2] + s[56:87] + s[28];
		return s.substring(7,28) + s.substr(87,1) + s.substring(29,45) + s.substr(55,1) + s.substring(46,55) + s.substr(2,1) + s.substring(56,87) + s.substr(28,1);
	} else if(s.length==87) {
	//	return s[6:27] + s[4] + s[28:39] + s[27] + s[40:59] + s[2] + s[60:];
		return s.substring(6,27) + s.substr(4,1) + s.substring(28,39) + s.substr(27,1) + s.substring(40,59) + s.substr(2,1) + s.substring(60);
	} else if(s.length==86) {
		s = reverse(s);
	//	return s[80:72:-1] + s[16] + s[71:39:-1] + s[72] + s[38:16:-1] + s[82] + s[15::-1];
		return s.substring(6,14)+s.substr(70,1)+s.substring(15,47)+s.substr(14,1)+s.substring(48,70)+s.substr(4,1)+s.substring(71);
	} else if(s.length==85) {
		//return s[3:11] + s[0] + s[12:55] + s[84] + s[56:84];
		return s.substring(3,11)+s.subtr(0,1)+s.substring(12,55)+s.subtr(84,1)+s.substring(56,84);
	} else if(s.length==84) {
		//return s[78:70:-1] + s[14] + s[69:37:-1] + s[70] + s[36:14:-1] + s[80] + s[:14][::-1];
		s = reverse(s);
		return s.substring(6,14)+s.substr(70,1)+s.substring(15,47)+s.substr(14,1)+s.substring(48,70)+s.substr(4,1)+s.substring(70)+s.substr(0,1);
	} else if(s.length==83) {
		s = reverse(s);
	//	return s[80:63:-1] + s[0] + s[62:0:-1] + s[63];
		return s.substring(3,20)+s.substr(83,1)+s.substring(21,83)+s.substr(20,1);
	} else if(s.length==82) {
		s = reverse(s);
	//	return s[80:37:-1] + s[7] + s[36:7:-1] + s[0] + s[6:0:-1] + s[37];
		return s.substring(2,45)+s.substr(75,1)+s.substring(46,75)+s.substr(82,1)+s.substring(76,82)+s.substr(45,1);
	} else if(s.length==81) {
		s = reverse(s);
	//	return s[56] + s[79:56:-1] + s[41] + s[55:41:-1] + s[80] + s[40:34:-1] + s[0] + s[33:29:-1] + s[34] + s[28:9:-1] + s[29] + s[8:0:-1] + s[9];
		return s.substr(25,1)+s.substring(2,25)+s.substr(40,1)+s.substring(26,40)+s.substr(1,1)+s.substring(41,47)+s.substr(81,1)+s.substring(48,52)+s.substr(47,1)+s.substring(53,72)+s.substr(52,1)+s.substring(73,81)+s.substr(72,1);
		//return s;
	} else if(s.length==80) {
	//	return s[1:19] + s[0] + s[20:68] + s[19] + s[69:80];
		return s.substring(1,19)+s.substr(0,1)+s.substring(20,68)+s.substr(19,1)+s.substring(69,80);
	} else if(s.length==79) {
		s = reverse(s);
	//	return s[54] + s[77:54:-1] + s[39] + s[53:39:-1] + s[78] + s[38:34:-1] + s[0] + s[33:29:-1] + s[34] + s[28:9:-1] + s[29] + s[8:0:-1] + s[9];	
		return s.substr(25,1)+s.substring(2,25)+s.substr(40,1)+s.substring(26,40)+s.substr(1,1)+s.substring(41,45)+s.substr(79,1)+s.substring(46,50)+s.substr(45,1)+s.substring(51,70)+s.substr(50,1)+s.substring(71,79)+s.substr(70,1);
	}
}
	
if (scrhead!=null&&scrhead!=""&&(wclh.indexOf("/watch?")!=-1)) {
	setCook();

    var select = document.createElement('select');
    var info = document.createElement('a');
    var gui = document.getElementById('watch-uploader-info');
    info.className = 'yt-uix-button yt-uix-button-default';
    gui.appendChild(select);
    gui.appendChild(info);
    info.innerText = "Click here (or save as) to download"
    select.onchange = function() {
        info.href = select.value;
        //document.location = select.value;
    }
	runIt(scrhead);
    select.innerHTML = html;
    select.onchange();
	setCook();
}