Skip to content

Instantly share code, notes, and snippets.

@pquerner
Created April 6, 2016 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pquerner/752fe04c39a7061bfd09eab216779bc7 to your computer and use it in GitHub Desktop.
Save pquerner/752fe04c39a7061bfd09eab216779bc7 to your computer and use it in GitHub Desktop.
node youtube-dl
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