Skip to content

Commit

Permalink
drop streamify, add downloadFromInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Jul 3, 2014
1 parent 20cba97 commit c76c9df
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 44 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ytdl(url, { filter: function(format) { return format.container === 'mp4'; } })

The returned readable stream emits these additional events.

### Event: 'info'
#### Event: 'info'
* `Object` - Info.
* `Object` - Format.

Expand All @@ -48,10 +48,17 @@ Use this if you only want to get metainfo from a video.

`options` gets passed to the `request()`, it can also have a `downloadURL` property set to `true` if you want ytdl to include the download url instead of the regular one. In some cases, a signature needs to be deciphered, and will require ytdl to make additional requests.

### ytdl.cache
### ytdl.downloadFromInfo(info, options)

A [memory cache](https://github.com/hij1nx/EventVat) is used to store information about recently retrieved videos. This is used to prevent double requests on videos that you want to retrieve the info of, and then download.
Once you have received metadata from a video with the `getInfo` function,
you may pass that `info`, along with other `options` to `downloadFromInfo`.

The returned readable stream emits these additional events:

#### Event: 'format'
* `Object` - Format.

Emitted when a format metadata has been chosen. `format.size` will also be available.

# Install

Expand Down
111 changes: 71 additions & 40 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,95 @@
var http = require('http');
var streamify = require('streamify');
var request = require('request');
var _ = require('underscore');
var getInfo = require('./info');
var crequest = require('./crequest');
var util = require('./util');
var http = require('http');
var PassThrough = require('stream').PassThrough;
var request = require('request');
var _ = require('underscore');
var getInfo = require('./info');
var crequest = require('./crequest');
var util = require('./util');

module.exports = ytdl;
ytdl.getInfo = getInfo;
ytdl.downloadFromInfo = downloadFromInfo;

/**
* @param {String} link
* @param {Object} options
* @return {ReadableStream}
*/
var ytdl = module.exports = function ytdl(link, options) {
var stream = streamify({
superCtor: http.ClientResponse,
readable: true,
writable: false
});

function ytdl(link, options) {
options = options || {};
options.downloadURL = true;

var stream = new PassThrough();

getInfo(link, options, function(err, info) {
if (err) {
stream.emit('error', err);
stream.readable = false;
return;
}

var format = util.chooseFormat(info.formats, options);
if (format instanceof Error) {
stream.emit('error', format);
return;
}

var requestOptions = _.clone(options);
requestOptions.url = format.url;
if (requestOptions.range) {
requestOptions.url += '&range=' + requestOptions.range;
}
delete requestOptions.quality;
delete requestOptions.range;
delete requestOptions.filter;

// Start downloading the video.
var req = request(requestOptions);
req.on('response', function(res) {
if (res.statusCode !== 200) {
stream.emit('error', new Error('status code ' + res.statusCode));
downloadFromInfoCallback(info, options, function(err, format, videoStream) {
if (err) {
stream.emit('error', err);
return;
}

format.size = res.headers['content-length'];
stream.emit('info', info, format);
videoStream.pipe(stream);
});
stream.resolve(req);
});

return stream;
};
}

ytdl.getInfo = getInfo;
function downloadFromInfoCallback(info, options, callback) {
options = options || {};

var format = util.chooseFormat(info.formats, options);
if (format instanceof Error) {
// The caller expects this function to be async.
setImmediate(callbackWithFormatError);
return;
}

var requestOptions = _.clone(options);
requestOptions.url = format.url;
if (requestOptions.range) {
requestOptions.url += '&range=' + requestOptions.range;
}
delete requestOptions.quality;
delete requestOptions.range;
delete requestOptions.filter;

// Start downloading the video.
var req = request(requestOptions);
req.on('error', callback);
req.on('response', function(res) {
if (res.statusCode !== 200) {
callback(new Error('status code ' + res.statusCode));
return;
}

format.size = res.headers['content-length'];
callback(null, format, req);
});

function callbackWithFormatError() {
callback(format);
}
}

function downloadFromInfo(info, options) {
var stream = new PassThrough();
options = options || {};

downloadFromInfoCallback(info, options, function(err, format, videoStream) {
if (err) {
stream.emit('error', err);
return;
}

stream.emit('format', format);
videoStream.pipe(stream);
});

return stream;
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"dependencies": {
"jstream": "~0.2.7",
"request": "~2.36.0",
"streamify": "~0.2.0",
"underscore": "~1.6.0"
},
"devDependencies": {
Expand Down

0 comments on commit c76c9df

Please sign in to comment.