├── Chrome-Extension
├── content-script.js
└── manifest.json
├── License
├── README.md
└── bookmarklet.js
/Chrome-Extension/content-script.js:
--------------------------------------------------------------------------------
1 | function getURLMap(bodyHTML) {
2 | var urlMap = null;
3 | var urlMapStartIndex = bodyHTML.indexOf('"url_encoded_fmt_stream_map"');
4 | if (urlMapStartIndex != -1) {
5 | urlMap = bodyHTML.substring(urlMapStartIndex);
6 | var urlMapEndIndex = urlMap.indexOf('", ');
7 | if (urlMapEndIndex != -1) {
8 | urlMap = urlMap.substring(30, urlMapEndIndex);
9 | }
10 | }
11 |
12 | if (urlMap == null) throw 'Error: Couldn\'t find url map.';
13 | urlMap = urlMap.replace(/\\u0026/g, '&');
14 | return urlMap;
15 | }
16 |
17 | function getLinksAndFormats(urlMap) {
18 | var allLinks = urlMap.split(',');
19 |
20 | var linksAndFormats = new Array();
21 | var numOfLinks = 0;
22 | for (var i = 0; i < allLinks.length; i++) {
23 | var link = getCleanURL(allLinks[i]);
24 | var itagIndex = link.lastIndexOf('itag=');
25 | if (itagIndex != -1) {
26 | var fmt = parseInt(link.substring(itagIndex + 5));
27 | if (!isNaN(fmt)) {
28 | linksAndFormats[fmt.toString()] = link;
29 | numOfLinks++;
30 | }
31 | // else {
32 | // alert('Ignoring link:\n' + link + '\nbecause tag at ' + itagIndex + ' is Nan.');
33 | // }
34 | }
35 | // else {
36 | // alert('Ignoring link:\n' + link + '\nbecause itag index coud not be found');
37 | // }
38 | }
39 |
40 | if (numOfLinks == 0) throw 'Failed to find download links.';
41 | linksAndFormats[0] = numOfLinks;
42 | return linksAndFormats;
43 | }
44 |
45 | function getKeyAndVal(str) {
46 | var m = str.match(/^([^=]*)=(.*)$/);
47 | if (m)
48 | return [m[1], m[2]];
49 | return null;
50 | }
51 |
52 | function getCleanURL(url) {
53 | var mainParams = {};
54 | var splits = url.split("&");
55 | for (var i = 0; i < splits.length; i++) {
56 | var keyVal = getKeyAndVal(splits[i]);
57 | if (keyVal) mainParams[keyVal[0]] = keyVal[1];
58 | }
59 |
60 | var cleanURL = null;
61 | if ('url' in mainParams)
62 | cleanURL = unescape(mainParams['url']);
63 |
64 | else {
65 | // use regex
66 | var regexes = ['url=(http.+?videoplayback.+?id=.+?)(\u0026|&)quality=', '(http.+?videoplayback.+?id=.+?)(\u0026|&)'];
67 | for (var i = 0; i < regexes.length; i++) {
68 | var match = new RegExp(regexes[i]).exec(url);
69 | if (match != null) {
70 | cleanURL = unescape(match[1]);
71 | break;
72 | }
73 | }
74 | }
75 |
76 | if (cleanURL) {
77 | // check for the signature
78 | if (cleanURL.indexOf('signature=') == -1 && cleanURL.indexOf('sig=') == -1) {
79 | var sig = null;
80 | if ('signature' in mainParams)
81 | sig = mainParams['signature'];
82 | else
83 | sig = mainParams['sig'];
84 |
85 | if (sig) cleanURL = cleanURL + '&signature=' + sig;
86 | }
87 | else if (cleanURL.indexOf('sig=') != -1) {
88 | cleanURL.replace(/sig=/g, 'signature=');
89 | }
90 |
91 | return cleanURL + '&title=' + document.title.match(/^(.*) - YouTube$/)[1];
92 | }
93 |
94 | return null;
95 | }
96 |
97 | function getHTMLForLinks(linksAndFormats) {
98 | var numOfLinks = linksAndFormats[0];
99 | var standardLinksHTML = '';
100 | var hdLinksHTML = '';
101 | var thereIsHD = false;
102 | var addDash = false;
103 | /** FMT mapping from youtube's videos' source:
104 | * 37 = 1920X1080 MP4
105 | * 46 = 1920X1080 WebM
106 | * 22 = 1280X720 MP4
107 | * 45 = 1280X720 WebM
108 | * 35 = Large FLV
109 | * 44 = Large WebM
110 | * 34 = Medium FLV
111 | * 18 = Medium MP4
112 | * 43 = Medium WebM
113 | * 5 = Small FLV
114 | */
115 |
116 | var addedSmall = false;
117 | if (linksAndFormats['5']) {
118 | standardLinksHTML += 'Small (FLV)%20%20%20%20%20';
119 | addDash = true;
120 | }
121 |
122 | var openedBracket = false,
123 | closedBracket = false;
124 | if (linksAndFormats['18']) {
125 | if (addDash) standardLinksHTML += ' - ';
126 | standardLinksHTML += 'Medium (MP4';
127 | addDash = false;
128 | openedBracket = true;
129 | }
130 |
131 | if (linksAndFormats['34']) {
132 | if (!openedBracket) standardLinksHTML += '- Medium (';
133 | else standardLinksHTML += ', ';
134 | standardLinksHTML += 'FLV';
135 | openedBracket = true;
136 | }
137 |
138 | if (linksAndFormats['43']) {
139 | if (!openedBracket) standardLinksHTML += '- Medium (';
140 | else standardLinksHTML += ', ';
141 | standardLinksHTML += 'WebM)';
142 | addDash = true;
143 | openedBracket = true;
144 | closedBracket = true;
145 | }
146 |
147 | if (openedBracket && !closedBracket) standardLinksHTML += ')';
148 | if (!addDash && (linksAndFormats['18'] || linksAndFormats['34'])) addDash = true;
149 | openedBracket = false, closedBracket = false;
150 |
151 | if (linksAndFormats['35']) {
152 | if (addDash) standardLinksHTML += ' - ';
153 | standardLinksHTML += 'Large (FLV';
154 | addDash = false;
155 | openedBracket = true;
156 | }
157 |
158 | if (linksAndFormats['44']) {
159 | if (!openedBracket) standardLinksHTML += '- Large (';
160 | else standardLinksHTML += ', ';
161 | standardLinksHTML += 'WebM)';
162 | addDash = true;
163 | openedBracket = true;
164 | closedBracket = true;
165 | }
166 | if (openedBracket && !closedBracket) standardLinksHTML += ')';
167 |
168 | addDash = false, openedBracket = false, closedBracket = false;
169 | if (linksAndFormats['22']) {
170 | hdLinksHTML += '720p (MP4';
171 | thereIsHD = true;
172 | addDash = true;
173 | openedBracket = true;
174 | }
175 |
176 | if (linksAndFormats['45']) {
177 | if (!openedBracket) hdLinksHTML += '- 720p (';
178 | else hdLinksHTML += ', ';
179 | hdLinksHTML += 'WebM)';
180 | thereIsHD = true;
181 | addDash = true;
182 | openedBracket = true;
183 | closedBracket = true;
184 | }
185 | if (openedBracket && !closedBracket) hdLinksHTML += ')';
186 |
187 | if (!addDash && (linksAndFormats['22'] || linksAndFormats['45'])) addDash = true;
188 | openedBracket = false, closedBracket = false;
189 |
190 | if (linksAndFormats['37']) {
191 | if (addDash) hdLinksHTML += ' - ';
192 | hdLinksHTML += '1080p (MP4';
193 | thereIsHD = true;
194 | addDash = true;
195 | openedBracket = true;
196 | }
197 | if (linksAndFormats['46']) {
198 | if (!openedBracket) hdLinksHTML += '- 1080p (';
199 | else hdLinksHTML += ', ';
200 | hdLinksHTML += 'WebM)';
201 | thereIsHD = true;
202 | addDash = true;
203 | openedBracket = true;
204 | closedBracket = true;
205 | }
206 | if (openedBracket && !closedBracket) hdLinksHTML += ')';
207 |
208 | var title = '
Download (' + numOfLinks + ' links found)
';
209 | if (thereIsHD) return unescape(title + standardLinksHTML + '
' + hdLinksHTML + '
');
210 | else return unescape(title + standardLinksHTML + '');
211 | }
212 |
213 | function start() {
214 | if (document.URL.indexOf('.youtube.com/watch?v=') == -1) return;
215 |
216 | var error = null;
217 | var urlMap = null;
218 | var linksAndFormats = null;
219 | try {
220 | urlMap = getURLMap(document.body.innerHTML);
221 | linksAndFormats = getLinksAndFormats(urlMap);
222 | } catch (err) {
223 | error = err;
224 | }
225 |
226 | var download_div = document.createElement('span');
227 | download_div.id = 'youtube-download-span';
228 | var style = download_div.style;
229 | style.padding = '5px';
230 | style.borderRadius = '1em';
231 | style.lineHeight = '1.6';
232 | style.display = 'inline-block';
233 | style.margin = '5px auto';
234 | style.boxShadow = '4px 4px 3px #999';
235 | style.border = '1px #999 solid';
236 | style.backgroundColor = '#ffe';
237 |
238 | if (error == null) {
239 | // Append the links to the div
240 | download_div.innerHTML = getHTMLForLinks(linksAndFormats);
241 | } else {
242 | // Display the error
243 | download_div.innerHTML = unescape('' + error + '
');
244 | }
245 | var container_div = document.createElement('div');
246 | container_div.style.textAlign = 'center';
247 | container_div.appendChild(download_div);
248 | document.body.insertBefore(container_div, document.body.firstChild);
249 | }
250 |
251 | start();
252 |
--------------------------------------------------------------------------------
/Chrome-Extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "YouTube Download",
4 | "description": "Shows the download links for youtube videos.",
5 | "version": "2.1.1",
6 | "permissions": ["http://www.youtube.com/*"],
7 | "content_scripts" : [
8 | {
9 | "matches" : [
10 | "http://www.youtube.com/*"
11 | ],
12 | "js" : ["content-script.js"],
13 | "run_at" : "document_end",
14 | "all_frames" : false
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/License:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012, Motasim Abdulaziz Alsayed
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 | DISCLAIMED. IN NO EVENT SHALL MOTASIM ABDULAZIZ ALSAYED BE LIABLE FOR ANY
16 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | There are two ways to use this script:
4 |
5 | 1. Using the bookmarklet: simply copy the code in the bookmarklet.js file and add it as a new bookmark. Then, whenever you're on a YT video page, click this bookmark to see the download links.
6 | 2. Using the Google Chrome extension: go to the extensions page in Chrome, and click on Load unpacked extension..., then choose the folder "Chrome-Extension". Then, whenever you visit a video page on youtube's domain (e.g. http://www.youtube.com/watch?v=_0-SJNnnHFM) the extension will load automatically.
7 |
8 | **Please, do not use this extension for any thing that would violate any copyrights.**
--------------------------------------------------------------------------------
/bookmarklet.js:
--------------------------------------------------------------------------------
1 | javascript:function%20getURLMap(bodyHTML){var%20urlMap=null;var%20urlMapStartIndex=bodyHTML.indexOf('"url_encoded_fmt_stream_map"');if(urlMapStartIndex!=-1){urlMap=bodyHTML.substring(urlMapStartIndex);var%20urlMapEndIndex=urlMap.indexOf('",%20');if(urlMapEndIndex!=-1){urlMap=urlMap.substring(0,urlMapEndIndex);}}if(urlMap==null)throw%20'Error:%20Couldn\'t%20find%20url%20map.';urlMap=urlMap.replace(/\\u0026/g,'&');return%20urlMap;}function%20getCleanURL(url){var%20mainParams={};var%20splits=url.split("&");for(var%20i=0;iFLV)%20%20%20%20%20';addDash=true;}var%20openedBracket=false,closedBracket=false;if(linksAndFormats['18']){if(addDash)standardLinksHTML+='%20-%20';standardLinksHTML+='Medium(MP4';addDash=false;openedBracket=true;}if(linksAndFormats['34']){if(!openedBracket)standardLinksHTML+='-%20Medium(';else%20standardLinksHTML+=',';standardLinksHTML+='FLV';openedBracket=true;}if(linksAndFormats['43']){if(!openedBracket)standardLinksHTML+='-%20Medium(';else%20standardLinksHTML+=',';standardLinksHTML+='WebM)';addDash=true;openedBracket=true;closedBracket=true;}if(openedBracket&&!closedBracket)standardLinksHTML+=')';if(!addDash&&(linksAndFormats['18']||linksAndFormats['34']))addDash=true;openedBracket=false,closedBracket=false;if(linksAndFormats['35']){if(addDash)standardLinksHTML+='%20-%20';standardLinksHTML+='Large(FLV';addDash=false;openedBracket=true;}if(linksAndFormats['44']){if(!openedBracket)standardLinksHTML+='-%20Large(';else%20standardLinksHTML+=',';standardLinksHTML+='WebM)';addDash=true;openedBracket=true;closedBracket=true;}if(openedBracket&&!closedBracket)standardLinksHTML+=')';addDash=false,openedBracket=false,closedBracket=false;if(linksAndFormats['22']){hdLinksHTML+='720p(MP4';thereIsHD=true;addDash=true;openedBracket=true;}if(linksAndFormats['45']){if(!openedBracket)hdLinksHTML+='-%20720p(';else%20hdLinksHTML+=',';hdLinksHTML+='WebM)';thereIsHD=true;addDash=true;openedBracket=true;closedBracket=true;}if(openedBracket&&!closedBracket)hdLinksHTML+=')';if(!addDash&&(linksAndFormats['22']||linksAndFormats['45']))addDash=true;openedBracket=false,closedBracket=false;if(linksAndFormats['37']){if(addDash)hdLinksHTML+='%20-%20';hdLinksHTML+='1080p(MP4';thereIsHD=true;addDash=true;openedBracket=true;}if(linksAndFormats['46']){if(!openedBracket)hdLinksHTML+='-%201080p(';else%20hdLinksHTML+=',';hdLinksHTML+='WebM)';thereIsHD=true;addDash=true;openedBracket=true;closedBracket=true;}if(openedBracket&&!closedBracket)hdLinksHTML+=')';var%20title='Download('+numOfLinks+'%20links%20found)
';if(thereIsHD)return%20unescape(title+standardLinksHTML+'
'+hdLinksHTML+'
');else%20return%20unescape(title+standardLinksHTML+'');}function%20start(){if(document.URL.indexOf('http://www.youtube.com/watch?v=')==-1)return;var%20error=null;var%20urlMap=null;var%20linksAndFormats=null;try{urlMap=getURLMap(document.body.innerHTML);linksAndFormats=getLinksAndFormats(urlMap);}catch(err){error=err;}var%20download_div=document.createElement('span');download_div.id='youtube-download-span';var%20style=download_div.style;style.padding='5px';style.borderRadius='1em';style.lineHeight='1.6';style.display='inline-block';style.margin='5px%20auto';style.boxShadow='4px%204px%203px%20#999';style.border='1px%20#999%20solid';style.backgroundColor='#ffe';if(error==null){download_div.innerHTML=getHTMLForLinks(linksAndFormats);}else{download_div.innerHTML=unescape(''+error+'
');}var%20container_div=document.createElement('div');container_div.style.textAlign='center';container_div.appendChild(download_div);document.body.insertBefore(container_div,document.body.firstChild);}start();
--------------------------------------------------------------------------------