refactor import by youtube url into plugin

This commit is contained in:
Andrew Kelley 2014-05-04 20:28:07 -07:00
parent cb6077bc87
commit fa21bdc3d2
2 changed files with 130 additions and 87 deletions

View file

@ -17,7 +17,6 @@ var safePath = require('./safe_path');
var PassThrough = require('stream').PassThrough; var PassThrough = require('stream').PassThrough;
var url = require('url'); var url = require('url');
var superagent = require('superagent'); var superagent = require('superagent');
var ytdl = require('ytdl');
module.exports = Player; module.exports = Player;
@ -26,16 +25,6 @@ groove.setLogging(groove.LOG_WARNING);
var cpuCount = require('os').cpus().length; var cpuCount = require('os').cpus().length;
// sorted from worst to best
var YTDL_AUDIO_ENCODINGS = [
'mp3',
'aac',
'wma',
'vorbis',
'wav',
'flac',
];
var PLAYER_KEY_PREFIX = "Player."; var PLAYER_KEY_PREFIX = "Player.";
var LIBRARY_KEY_PREFIX = "Library."; var LIBRARY_KEY_PREFIX = "Library.";
var LIBRARY_DIR_PREFIX = "LibraryDir."; var LIBRARY_DIR_PREFIX = "LibraryDir.";
@ -268,6 +257,8 @@ function Player(db, musicDirectory, instantBufferBytes) {
this.expectHeaders = true; this.expectHeaders = true;
this.playlistItemDeleteQueue = []; this.playlistItemDeleteQueue = [];
this.importUrlFilters = [];
} }
Player.prototype.initialize = function(cb) { Player.prototype.initialize = function(cb) {
@ -797,19 +788,34 @@ Player.prototype.importUrl = function(urlString, cb) {
cb = cb || logIfError; cb = cb || logIfError;
var tmpDir = path.join(self.musicDirectory, '.tmp'); var tmpDir = path.join(self.musicDirectory, '.tmp');
var filterIndex = 0;
mkdirp(tmpDir, function(err) { mkdirp(tmpDir, function(err) {
if (err) return cb(err); if (err) return cb(err);
var parsedUrl = url.parse(urlString); tryImportFilter();
});
// detect youtube downloads function tryImportFilter() {
if ((parsedUrl.hostname === 'youtube.com' || parsedUrl.hostname === 'www.youtube.com') && var importPlugin = self.importUrlFilters[filterIndex];
parsedUrl.pathname === '/watch') if (importPlugin) {
{ importPlugin.importUrl(urlString, callNextFilter);
var bestFormat = null;
ytdl.getInfo(urlString, gotYouTubeInfo);
} else { } else {
downloadRaw();
}
function callNextFilter(err, dlStream, filename) {
if (err || !dlStream) {
if (err) console.warn("import filter error, skipping:", err.stack);
filterIndex += 1;
tryImportFilter();
return;
}
handleDownload(dlStream, filename);
}
}
function downloadRaw() {
var parsedUrl = url.parse(urlString);
var remoteFilename = path.basename(parsedUrl.pathname); var remoteFilename = path.basename(parsedUrl.pathname);
var decodedFilename; var decodedFilename;
try { try {
@ -821,30 +827,6 @@ Player.prototype.importUrl = function(urlString, cb) {
handleDownload(req, decodedFilename); handleDownload(req, decodedFilename);
} }
function gotYouTubeInfo(err, info) {
if (err) return cb(err);
for (var i = 0; i < info.formats.length; i += 1) {
var format = info.formats[i];
if (bestFormat == null || format.audioBitrate > bestFormat.audioBitrate ||
(format.audioBitrate === bestFormat.audioBitrate &&
YTDL_AUDIO_ENCODINGS.indexOf(format.audioEncoding) >
YTDL_AUDIO_ENCODINGS.indexOf(bestFormat.audioEncoding)))
{
bestFormat = format;
}
}
if (YTDL_AUDIO_ENCODINGS.indexOf(bestFormat.audioEncoding) === -1) {
console.warn("YouTube Import: unrecognized audio format:", bestFormat.audioEncoding);
}
var req = ytdl(urlString, {filter: filter});
handleDownload(req, info.title + '.' + bestFormat.container);
function filter(format) {
return format.audioBitrate === bestFormat.audioBitrate &&
format.audioEncoding === bestFormat.audioEncoding;
}
}
function handleDownload(req, remoteFilename) { function handleDownload(req, remoteFilename) {
var ext = path.extname(remoteFilename); var ext = path.extname(remoteFilename);
var destPath = path.join(tmpDir, uuid() + ext); var destPath = path.join(tmpDir, uuid() + ext);
@ -877,7 +859,6 @@ Player.prototype.importUrl = function(urlString, cb) {
cb(err); cb(err);
} }
} }
});
function logIfError(err) { function logIfError(err) {
if (err) { if (err) {

62
lib/plugins/ytdl.js Normal file
View file

@ -0,0 +1,62 @@
var ytdl = require('ytdl');
var url = require('url');
module.exports = YtDlPlugin;
// sorted from worst to best
var YTDL_AUDIO_ENCODINGS = [
'mp3',
'aac',
'wma',
'vorbis',
'wav',
'flac',
];
function YtDlPlugin(gb) {
gb.player.importUrlFilters.push(this);
}
YtDlPlugin.prototype.importUrl = function(urlString, cb) {
var parsedUrl = url.parse(urlString);
var isYouTube = (parsedUrl.pathname === '/watch' &&
(parsedUrl.hostname === 'youtube.com' ||
parsedUrl.hostname === 'www.youtube.com' ||
parsedUrl.hostname === 'm.youtube.com')) ||
parsedUrl.hostname === 'youtu.be' ||
parsedUrl.hostname === 'www.youtu.be';
if (!isYouTube) {
cb();
return;
}
var bestFormat = null;
ytdl.getInfo(urlString, gotYouTubeInfo);
function gotYouTubeInfo(err, info) {
if (err) return cb(err);
for (var i = 0; i < info.formats.length; i += 1) {
var format = info.formats[i];
if (bestFormat == null || format.audioBitrate > bestFormat.audioBitrate ||
(format.audioBitrate === bestFormat.audioBitrate &&
YTDL_AUDIO_ENCODINGS.indexOf(format.audioEncoding) >
YTDL_AUDIO_ENCODINGS.indexOf(bestFormat.audioEncoding)))
{
bestFormat = format;
}
}
if (YTDL_AUDIO_ENCODINGS.indexOf(bestFormat.audioEncoding) === -1) {
console.warn("YouTube Import: unrecognized audio format:", bestFormat.audioEncoding);
}
var req = ytdl(urlString, {filter: filter});
var filename = info.title + '.' + bestFormat.container;
cb(null, req, filename);
function filter(format) {
return format.audioBitrate === bestFormat.audioBitrate &&
format.audioEncoding === bestFormat.audioEncoding;
}
}
};