refactor import by youtube url into plugin
This commit is contained in:
parent
cb6077bc87
commit
fa21bdc3d2
2 changed files with 130 additions and 87 deletions
|
|
@ -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
62
lib/plugins/ytdl.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue