youtube-mp3-downloader
Advanced tools
Comparing version 0.1.0 to 0.2.0
"use strict"; | ||
var os = require('os'); | ||
var util = require('util'); | ||
var EventEmitter = require("events").EventEmitter; | ||
var ffmpeg = require('fluent-ffmpeg'); | ||
var ytdl = require('ytdl-core'); | ||
var async = require('async'); | ||
var progress = require('progress-stream'); | ||
@@ -14,3 +17,4 @@ function YoutubeMp3Downloader(options) { | ||
self.outputPath = (options && options.outputPath ? options.outputPath : (os.platform() === 'win32' ? 'D:/temp' : '/tmp')); | ||
self.parallelismFactor = (options && options.parallelismFactor ? options.parallelismFactor : 1); | ||
self.queueParallelism = (options && options.queueParallelism ? options.queueParallelism : 1); | ||
self.progressTimeout = (options && options.progressTimeout ? options.progressTimeout : 1000); | ||
@@ -21,73 +25,107 @@ if (options && options.ffmpegPath) { | ||
//Async download/transcode queue | ||
self.downloadQueue = async.queue(function (videoId, callback) { | ||
self.performDownload(videoId, function(err, result) { | ||
callback(err, result); | ||
}); | ||
}, self.queueParallelism); | ||
} | ||
YoutubeMp3Downloader.prototype.download = function(videoInfo, cb) { | ||
util.inherits(YoutubeMp3Downloader, EventEmitter); | ||
YoutubeMp3Downloader.prototype.download = function(videoId) { | ||
var self = this; | ||
var videoArray = []; | ||
if (Array.isArray(videoInfo)) { | ||
videoArray = videoInfo; | ||
} else if (typeof videoInfo === "string") { | ||
videoArray.push(videoInfo); | ||
} | ||
self.downloadQueue.push(videoId, function (err, data) { | ||
if (err) { | ||
self.emit("error", err); | ||
} else { | ||
self.emit('finished', data); | ||
} | ||
}); | ||
function getVideo(videoId, callback) { | ||
}; | ||
var videoUrl = self.youtubeBaseUrl+videoId; | ||
YoutubeMp3Downloader.prototype.performDownload = function(videoId, cb) { | ||
ytdl.getInfo(videoUrl, function(err, info){ | ||
var self = this; | ||
var videoUrl = self.youtubeBaseUrl+videoId; | ||
var videoTitle = info.title.replace(/"/g, '').replace(/'/g, '').replace(/\//g, '').replace(/\?/g, ''); | ||
var artist = "Unknown"; | ||
var title = "Unknown"; | ||
ytdl.getInfo(videoUrl, function(err, info){ | ||
if (videoTitle.indexOf("-") > -1) { | ||
var temp = videoTitle.split("-"); | ||
if (temp.length >= 2) { | ||
artist = temp[0].trim(); | ||
title = temp[1].trim(); | ||
} | ||
} else { | ||
title = videoTitle; | ||
var videoTitle = info.title.replace(/"/g, '').replace(/'/g, '').replace(/\//g, '').replace(/\?/g, ''); | ||
var artist = "Unknown"; | ||
var title = "Unknown"; | ||
if (videoTitle.indexOf("-") > -1) { | ||
var temp = videoTitle.split("-"); | ||
if (temp.length >= 2) { | ||
artist = temp[0].trim(); | ||
title = temp[1].trim(); | ||
} | ||
} else { | ||
title = videoTitle; | ||
} | ||
var stream = ytdl(videoUrl, { | ||
quality: self.youtubeVideoQuality | ||
var fileName = self.outputPath + '/' + videoTitle + '.mp3'; | ||
var stream = ytdl(videoUrl, { | ||
quality: self.youtubeVideoQuality | ||
}); | ||
stream.on("info", function(info, format) { | ||
var resultObj = {}; | ||
//Setup of progress module | ||
var str = progress({ | ||
length: format.size, | ||
time: self.progressTimeout | ||
}); | ||
var fileName = self.outputPath + '/' + videoTitle + '.mp3'; | ||
var startTimestamp = new Date().getTime(); | ||
//Add progress event listener | ||
str.on('progress', function(progress) { | ||
if (progress.percentage === 100) { | ||
resultObj.stats= { | ||
transferredBytes: progress.transferred, | ||
runtime: progress.runtime, | ||
averageSpeed: parseFloat(progress.speed.toFixed(2)) | ||
} | ||
} | ||
self.emit("progress", {videoId: videoId, progress: progress}) | ||
}); | ||
//Pipe through progress module | ||
var videoStream = stream.pipe(str); | ||
//Start encoding | ||
var proc = new ffmpeg({ | ||
source: stream | ||
source: videoStream | ||
}) | ||
.audioBitrate(info.formats[0].audioBitrate) | ||
.withAudioCodec('libmp3lame') | ||
.toFormat('mp3') | ||
.outputOptions('-id3v2_version', '4') | ||
.outputOptions('-metadata', 'title=' + title) | ||
.outputOptions('-metadata', 'artist=' + artist) | ||
.on('error', function(err) { | ||
console.log('An error occurred: ' + err.message); | ||
callback(err.message, null); | ||
}) | ||
.on('end', function() { | ||
//console.log('Processing finished !'); | ||
callback(null, { | ||
"file": fileName, | ||
"videoId": videoId, | ||
"youtubeUrl": videoUrl, | ||
"videoTitle": videoTitle, | ||
"artist": artist, | ||
"title": title, | ||
"took": (new Date().getTime()-startTimestamp) | ||
}); | ||
}) | ||
.saveToFile(fileName); | ||
.audioBitrate(info.formats[0].audioBitrate) | ||
.withAudioCodec('libmp3lame') | ||
.toFormat('mp3') | ||
.outputOptions('-id3v2_version', '4') | ||
.outputOptions('-metadata', 'title=' + title) | ||
.outputOptions('-metadata', 'artist=' + artist) | ||
.on('error', function(err) { | ||
cb(err.message, null); | ||
}) | ||
.on('end', function() { | ||
resultObj.file = fileName; | ||
resultObj.videoId = videoId; | ||
resultObj.youtubeUrl = videoUrl; | ||
resultObj.videoTitle = videoTitle; | ||
resultObj.artist = artist; | ||
resultObj.title = title; | ||
cb(null, resultObj); | ||
}) | ||
.saveToFile(fileName); | ||
}); | ||
} | ||
async.mapLimit(videoArray, self.parallelismFactor, getVideo, function(err, results){ | ||
cb(results); | ||
}); | ||
@@ -97,2 +135,2 @@ | ||
module.exports = YoutubeMp3Downloader; | ||
module.exports = YoutubeMp3Downloader; |
{ | ||
"name": "youtube-mp3-downloader", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "Downloads Youtube videos (in parallel, as streams), encodes the audio data as mp3 and stores them in a defineable location", | ||
@@ -21,5 +21,6 @@ "keywords": [ | ||
"dependencies": { | ||
"ytdl-core": "0.4.1", | ||
"fluent-ffmpeg": "2.0.0-rc3", | ||
"async": "0.9.0" | ||
"async": "1.2.1", | ||
"fluent-ffmpeg": "2.0.1", | ||
"progress-stream": "^1.1.1", | ||
"ytdl-core": "0.5.1" | ||
}, | ||
@@ -26,0 +27,0 @@ "author": { |
# Youtube MP3 Downloader | ||
Youtube MP3 Downloader is a module which allows to specify one or multiple YouTube videos from whom the audio data should be extracted, converted to MP3, and stored on disk. | ||
Youtube MP3 Downloader is a module which allows to specify YouTube videos from which the audio data should be extracted, converted to MP3, and stored on disk. | ||
@@ -28,12 +28,23 @@ ## Installation | ||
var YD = new YoutubeMp3Downloader({ | ||
"ffmpegPath": "/path/to/ffmpeg", //Where is the FFmpeg binary located? | ||
"outputPath": "/path/to/mp3/folder", //Where should the downloaded and encoded files be stored? | ||
"youtubeVideoQuality": "highest", //What video quality should be used? | ||
"parallelismFactor": 2 //How many parallel downloads/encodes should be started? | ||
"ffmpegPath": "/path/to/ffmpeg", // Where is the FFmpeg binary located? | ||
"outputPath": "/path/to/mp3/folder", // Where should the downloaded and encoded files be stored? | ||
"youtubeVideoQuality": "highest", // What video quality should be used? | ||
"queueParallelism": 2, // How many parallel downloads/encodes should be started? | ||
"progressTimeout": 2000 // How long should be the interval of the progress reports | ||
}); | ||
//Download video and save as MP3 file | ||
YD.download(["rnkuRQ8tjIE"], function(result) { | ||
console.log(result); | ||
YD.download("rnkuRQ8tjIE"); | ||
YD.on("finished", function(data) { | ||
console.log(data); | ||
}); | ||
YD.on("error", function(error) { | ||
console.log(error); | ||
}); | ||
YD.on("progress", function(progress) { | ||
console.log(progress); | ||
}); | ||
``` | ||
@@ -44,13 +55,15 @@ | ||
```javascript | ||
[ | ||
{ | ||
"file": "/path/to/mp3/folder/Nancy Sinatra & Lee Hazlewood - Jackson.mp3", | ||
"videoId": "rnkuRQ8tjIE", | ||
"youtubeUrl": "http: //www.youtube.com/watch?v=rnkuRQ8tjIE", | ||
"videoTitle": "Nancy Sinatra & Lee Hazlewood - Jackson", | ||
"artist": "Nancy Sinatra & Lee Hazlewood", | ||
"title": "Jackson", | ||
"took": 17708 | ||
{ | ||
"videoId": "rnkuRQ8tjIE", | ||
"file": "/path/to/mp3/folder/Nancy Sinatra & Lee Hazlewood - Jackson.mp3", | ||
"youtubeUrl": "http://www.youtube.com/watch?v=rnkuRQ8tjIE", | ||
"videoTitle": "Nancy Sinatra & Lee Hazlewood - Jackson", | ||
"artist": "Nancy Sinatra & Lee Hazlewood", | ||
"title": "Jackson", | ||
"stats": { | ||
"transferred": 7315910, | ||
"runtime": 9, | ||
"averageSpeed": 713747.31 | ||
} | ||
] | ||
} | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
8961
103
67
4
+ Addedprogress-stream@^1.1.1
+ AddedCSSselect@0.4.1(transitive)
+ AddedCSSwhat@0.4.7(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasync@1.2.1(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcheerio@0.18.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcore-util-is@1.0.21.0.3(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addeddom-serializer@0.0.1(transitive)
+ Addeddomelementtype@1.1.3(transitive)
+ Addeddomhandler@2.3.0(transitive)
+ Addeddomutils@1.4.31.5.1(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedentities@1.0.01.1.2(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfluent-ffmpeg@2.0.1(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhtmlparser2@3.8.3(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisarray@0.0.1(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedlodash@2.4.2(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedobject-keys@0.4.0(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedprogress-stream@1.2.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedreadable-stream@1.1.14(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedspeedometer@0.1.4(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedthrough2@0.2.3(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addedunderscore@1.13.7(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)
+ Addedxtend@2.1.2(transitive)
+ Addedytdl-core@0.5.1(transitive)
- Removedasn1@0.1.11(transitive)
- Removedassert-plus@0.1.5(transitive)
- Removedasync@0.9.0(transitive)
- Removedaws-sign2@0.5.0(transitive)
- Removedboom@0.4.2(transitive)
- Removedcombined-stream@0.0.7(transitive)
- Removedcryptiles@0.2.2(transitive)
- Removedctype@0.5.3(transitive)
- Removeddelayed-stream@0.0.5(transitive)
- Removedfluent-ffmpeg@2.0.0-rc3(transitive)
- Removedforever-agent@0.5.2(transitive)
- Removedform-data@0.1.4(transitive)
- Removedhawk@1.1.1(transitive)
- Removedhoek@0.9.1(transitive)
- Removedhttp-signature@0.10.1(transitive)
- Removedmime@1.2.11(transitive)
- Removedmime-types@1.0.2(transitive)
- Removednode-uuid@1.4.8(transitive)
- Removedoauth-sign@0.3.0(transitive)
- Removedqs@0.6.6(transitive)
- Removedrequest@2.37.0(transitive)
- Removedsntp@0.2.4(transitive)
- Removedtldts@6.1.77(transitive)
- Removedtldts-core@6.1.77(transitive)
- Removedtough-cookie@5.1.1(transitive)
- Removedtunnel-agent@0.4.3(transitive)
- Removedunderscore@1.6.0(transitive)
- Removedytdl-core@0.4.1(transitive)
Updatedasync@1.2.1
Updatedfluent-ffmpeg@2.0.1
Updatedytdl-core@0.5.1