refactored artwork extraction

This commit is contained in:
Daniel Sommer 2017-03-27 23:27:33 +02:00
parent b1d7fffb2d
commit 33c725f7ae
3 changed files with 66 additions and 79 deletions

View file

@ -5,7 +5,6 @@ const os = require('os');
const path = require('path'); const path = require('path');
const async = require('async'); const async = require('async');
const commander = require('commander'); const commander = require('commander');
const recursive = require('recursive-readdir');
const app = require('./package.json'); const app = require('./package.json');
const audio = require('./lib/audio'); const audio = require('./lib/audio');
const util = require('./lib/util'); const util = require('./lib/util');
@ -51,82 +50,39 @@ function run() {
commander.parse(process.argv); commander.parse(process.argv);
} }
// create config object // convert files
function getConfig(input, output, options, commander) { function convert(input, output, options) {
return { audio.batchConvert({
input: path.normalize(input), input: path.normalize(input),
output: path.normalize(output), output: path.normalize(output),
concurrency: commander.concurrency || os.cpus().length, concurrency: commander.concurrency || os.cpus().length,
bitrate: options.bitrate || 320, bitrate: options.bitrate || 320,
format: options.format || '.flac' format: options.format || '.flac'
} }, function (err) {
}
// convert files
function convert(input, output, options) {
audio.batchConvert(getConfig(input, output, options, commander), function (err) {
cli.exit(err); cli.exit(err);
}); });
} }
// sort files // sort files
function sort(input, output, options) { function sort(input, output, options) {
util.batchSort(getConfig(input, output, options, commander), function (err) { util.batchSort({
input: path.normalize(input),
output: path.normalize(output),
concurrency: commander.concurrency || os.cpus().length,
bitrate: options.bitrate || 320,
format: options.format || '.flac'
}, function (err) {
cli.exit(err); cli.exit(err);
})
}
// move file to location defined by its metadata
function processFileSort(output, sourceFile, callback) {
async.waterfall([
function (asyncCallback) {
audio.extractMetadata(sourceFile, asyncCallback)
},
function (sourceFile, metadata, asyncCallback) {
util.pathFromMetadata(sourceFile, output, metadata, asyncCallback);
},
function (targetFile, asyncCallback) {
util.moveFile(sourceFile, targetFile, asyncCallback);
}
], function (err, results) {
if (err) {
return callback(err);
}
callback(null, results);
}); });
} }
// extract artwork // extract artwork
function artwork(input, options) { function artwork(input, options) {
async.waterfall([ audio.batchArtwork({
function (asyncCallback) { input: path.normalize(input),
recursive(input, [ignoreFilter], asyncCallback); concurrency: commander.concurrency || os.cpus().length,
}, format: options.format || '.flac'
function (files, asyncCallback) { }, function (err) {
console.log(files.length + ' \'' + options.format + '\' files found'); cli.exit(err);
// display progressbar
const bar = util.createProgressBar(files.length);
// handle each file
async.eachLimit(files, commander.concurrency, function (file, eachCallback) {
audio.extractArtwork(file, function (err) {
bar.tick();
if (err) {
return eachCallback(err);
}
eachCallback();
});
}, function (err) {
if (err) {
return asyncCallback(err);
}
asyncCallback();
});
}
], function (err, result) {
util.exit(err, start);
}); });
function ignoreFilter(file, stats) {
return !stats.isDirectory() && path.extname(file).indexOf(options.format) == -1;
}
} }

View file

@ -73,27 +73,57 @@ function convert(source, config, callback) {
], callback); ], callback);
} }
// extract cover artwork //
function extractArtwork(sourceFile, callback) { function batchArtwork(config, callback) {
async.waterfall([ async.waterfall([
function (asyncCallback) { // get files
extractMetadata(sourceFile, asyncCallback); function (waterfallCallback) {
util.readDirRecursive(config.input, config.format, waterfallCallback);
}, },
function (metadata, asyncCallback) { // display info, prompt user and create progressbar
metadata.picture.forEach(function (picture) { function (files, waterfallCallback) {
const pic = path.join(path.dirname(sourceFile), path.basename(sourceFile, path.extname(sourceFile)) + '.' + picture.format); cli.askForConfirmation(files.length + ' files found.\nstart artwork extraction now?', ['yes', 'y'], function (err) {
const stream = fs.createWriteStream(pic); if (err) {
stream.write(picture.data); return waterfallCallback(err);
stream.end(); }
asyncCallback(); waterfallCallback(null, files, cli.createProgressBar(files.length));
}); });
},
// process each file
function (files, bar, waterfallCallback) {
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
extractArtwork(file, function (err) {
bar.tick();
if (err) {
return eachCallback(err);
}
eachCallback();
});
}, waterfallCallback);
} }
], function (err, result) { ], callback);
if (err) { }
return callback(err);
// extract cover artwork
function extractArtwork(source, callback) {
async.waterfall([
// get metadata
function (waterfallCallback) {
extractMetadata(source, waterfallCallback);
},
// write image to disk
function (metadata, waterfallCallback) {
if (!metadata.picture) {
waterfallCallback();
}
for (let counter = 0, length = metadata.picture.length; counter < length; counter++) {
const stream = fs.createWriteStream(path.join(path.dirname(source), path.basename(source, path.extname(source)) + '.' + metadata.picture[counter].format));
stream.write(metadata.picture[counter].data);
stream.end();
}
waterfallCallback();
} }
callback(); ], callback);
});
} }
// extract metadata for further processing // extract metadata for further processing
@ -109,7 +139,8 @@ function extractMetadata(sourceFile, callback) {
} }
// api // api
exports.convert = convert;
exports.batchConvert = batchConvert; exports.batchConvert = batchConvert;
exports.convert = convert;
exports.batchArtwork = batchArtwork;
exports.extractArtwork = extractArtwork; exports.extractArtwork = extractArtwork;
exports.extractMetadata = extractMetadata; exports.extractMetadata = extractMetadata;

View file

@ -1,6 +1,6 @@
{ {
"name": "badger-am", "name": "badger-am",
"version": "0.5.1", "version": "0.5.2",
"license": "MIT", "license": "MIT",
"description": "audio manager", "description": "audio manager",
"author": "Daniel Sommer <daniel.sommer@velvettear.de>", "author": "Daniel Sommer <daniel.sommer@velvettear.de>",