Created
April 6, 2016 11:37
-
-
Save pquerner/752fe04c39a7061bfd09eab216779bc7 to your computer and use it in GitHub Desktop.
node youtube-dl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var https = require('https'); | |
var async = require('async'); | |
var path = require('path'); | |
var fs = require('fs'); | |
var ytdl = require('youtube-dl'); | |
var ytchannelids = ['UCrsECiuZUe7HObWu7UF--5A', 'valvenewsnetwork']; //channels to download, not yet used | |
var ytchannelid = 'UCrsECiuZUe7HObWu7UF--5A'; //channel to download, new format | |
var youtubeids = []; | |
//'valvenewsnetwork'; | |
var apikey = 'xxxx'; //youtube api key | |
var jsoncontent = ''; | |
//Grab latest video | |
//final url https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername={channelname}&key={apikey} (old) | |
//final url https://www.googleapis.com/youtube/v3/search?key={your_key_here}&channelId={channel_id_here}&part=snippet,id&order=date&maxResults=20 | |
var options = { | |
host : 'www.googleapis.com', //path: '/youtube/v3/channels?part=contentDetails&forUsername=' + ytchannelid + '&key=' + apikey | |
path : '/youtube/v3/search?key=' + apikey + '&channelId=' + ytchannelid + '&part=snippet,id&order=date&maxResults=20', | |
}; | |
//traverse object, or encode to json object and traverse this | |
//todo add failure, if str cannot be converted to json obj | |
function traverse(o, callback) { | |
var type = typeof o; | |
if (type == "object") { | |
for (var key in o) { | |
traverse(o[key], callback); | |
} | |
} | |
else { | |
JSON.parse(o, function (key, value) { | |
if (key !== '') { | |
callback.call(this, key, value); | |
} | |
return value; | |
} | |
); | |
} | |
} | |
callback = function (response) { | |
var str = ''; | |
//build json string from body | |
response.on('data', function (chunk) { | |
str += chunk; | |
} | |
); | |
response.on('end', function () { | |
//traverse from json string and build my array of youtube video ids | |
traverse(str, function (key, value) { | |
switch (key) { | |
case 'videoId': | |
youtubeids.push(value); | |
//console.log(youtubeids); | |
break; | |
default : break; | |
} | |
} | |
); | |
//console.log(youtubeids); | |
//finally have my array of youtube ids, now give it to the download func | |
DLVideos(youtubeids); | |
} | |
); | |
} | |
//make the call to youtube api to get the videos | |
https.get(options, callback); | |
function DLVideos(youtubeids) { | |
async.each(youtubeids, function (singleVideoId, nextItem) { | |
var downloaded = 0; | |
//build output file name {video_id}.mp4 - will later be renamed to {video_title}.mp4 | |
var output = singleVideoId + '.mp4'; | |
var size = 0; | |
if (fs.existsSync(output)) { downloaded = fs.statSync(output).size; } | |
//console.log(downloaded); | |
var video = ytdl('https://www.youtube.com/watch?v=' + singleVideoId, | |
// Optional arguments passed to youtube-dl. | |
['--format=best'], | |
// start will be sent as a range header | |
{start: downloaded, cwd: __dirname}); | |
// Will be called when the download starts. | |
video.on('info', function(info) { | |
'use strict'; | |
//console.log('Download started'); | |
//console.log('filename: ' + info._filename); | |
// info.size will be the amount to download, add | |
var total = info.size + downloaded; | |
//console.log('size: ' + total); | |
size = info.size; | |
if (downloaded > 0) { | |
// size will be the amount already downloaded | |
console.log('resuming from: ' + downloaded); | |
// display the remaining bytes to download | |
console.log('remaining bytes: ' + info.size); | |
} | |
}); | |
video.pipe(fs.createWriteStream(output, {flags: 'a'})); | |
// Will be called if download was already completed and there is nothing more to download. | |
video.on('complete', function complete(info) { | |
'use strict'; | |
//console.log('filename: ' + info._filename + ' already downloaded.'); | |
console.log("\nRenaming"); | |
console.log(output); | |
console.log("to"); | |
console.log(info._filename); | |
console.log("\n"); | |
fs.renameSync(output, info._filename) | |
//callback to let async know we're ready for the next item | |
nextItem(); | |
}); | |
video.on('end', function end() { | |
'use strict'; | |
console.log('finished downloading!'); | |
}); | |
var pos = 0; | |
video.on('data', function data(chunk) { | |
'use strict'; | |
pos += chunk.length; | |
// `size` should not be 0 here. | |
if (size) { | |
var percent = (pos / size * 100).toFixed(2); | |
process.stdout.cursorTo(0); | |
process.stdout.clearLine(1); | |
process.stdout.write(percent + '%'); | |
} | |
} | |
); | |
} | |
, function (err) { | |
// downloaded all | |
} | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment