implemented scan functionality
This commit is contained in:
parent
db6b470694
commit
71918aedd5
32
badger-am.js
32
badger-am.js
|
@ -34,10 +34,10 @@ function badger() {
|
||||||
.action(sort);
|
.action(sort);
|
||||||
// artwork
|
// artwork
|
||||||
commander
|
commander
|
||||||
.command('artwork <input>')
|
.command('extract <input>')
|
||||||
.description('extract cover artwork')
|
.description('extract cover artwork')
|
||||||
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
||||||
.action(artwork);
|
.action(extract);
|
||||||
// scan
|
// scan
|
||||||
commander
|
commander
|
||||||
.command('scan <input>')
|
.command('scan <input>')
|
||||||
|
@ -70,22 +70,42 @@ function sort(input, output, options) {
|
||||||
bitrate: options.bitrate || 320,
|
bitrate: options.bitrate || 320,
|
||||||
format: options.format || '.flac'
|
format: options.format || '.flac'
|
||||||
}, function (err, time) {
|
}, function (err, time) {
|
||||||
cli.exit(err);
|
cli.exit(err, time);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract artwork
|
// extract artwork
|
||||||
function artwork(input, options) {
|
function extract(input, options) {
|
||||||
audio.batchArtwork({
|
audio.batchArtwork({
|
||||||
input: path.normalize(input),
|
input: path.normalize(input),
|
||||||
concurrency: commander.concurrency || os.cpus().length,
|
concurrency: commander.concurrency || os.cpus().length,
|
||||||
format: options.format || '.flac'
|
format: options.format || '.flac'
|
||||||
}, function (err, time) {
|
}, function (err, time) {
|
||||||
cli.exit(err);
|
cli.exit(err, time);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan files
|
// scan files
|
||||||
function scan(input, options) {
|
function scan(input, options) {
|
||||||
|
audio.batchScan({
|
||||||
|
input: path.normalize(input),
|
||||||
|
concurrency: commander.concurrency || os.cpus().length,
|
||||||
|
format: options.format || '.flac'
|
||||||
|
}, function (err, missing, time) {
|
||||||
|
if (!missing || missing.length === 0) {
|
||||||
|
console.log('no files with missing cover artwork found');
|
||||||
|
cli.exit(err, time);
|
||||||
|
} else {
|
||||||
|
console.log(missing.length + ' files with missing cover artwork found after ' + util.getTimeDiff(time) + ' seconds');
|
||||||
|
cli.askForConfirmation('list files now?', ['yes', 'y'], function (canceled) {
|
||||||
|
if (canceled) {
|
||||||
|
cli.exit(err, time);
|
||||||
|
}
|
||||||
|
missing.forEach(function (file) {
|
||||||
|
console.log(file);
|
||||||
|
});
|
||||||
|
cli.exit(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
60
lib/audio.js
60
lib/audio.js
|
@ -81,8 +81,8 @@ function convert(source, config, callback) {
|
||||||
], callback);
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// extract all covers
|
||||||
function batchArtwork(config, callback) {
|
function batchExtract(config, callback) {
|
||||||
let timestamp = process.hrtime();
|
let timestamp = process.hrtime();
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
// get files
|
// get files
|
||||||
|
@ -103,7 +103,7 @@ function batchArtwork(config, callback) {
|
||||||
function (files, bar, waterfallCallback) {
|
function (files, bar, waterfallCallback) {
|
||||||
timestamp = process.hrtime();
|
timestamp = process.hrtime();
|
||||||
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
||||||
extractArtwork(file, function (err) {
|
artwork(file, function (err) {
|
||||||
bar.tick();
|
bar.tick();
|
||||||
if (err) {
|
if (err) {
|
||||||
return eachCallback(err);
|
return eachCallback(err);
|
||||||
|
@ -121,7 +121,7 @@ function batchArtwork(config, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract cover artwork
|
// extract cover artwork
|
||||||
function extractArtwork(source, callback) {
|
function artwork(source, callback) {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
// get metadata
|
// get metadata
|
||||||
function (waterfallCallback) {
|
function (waterfallCallback) {
|
||||||
|
@ -142,9 +142,52 @@ function extractArtwork(source, callback) {
|
||||||
], callback);
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan files in input directory for missing cover artwork
|
||||||
|
function batchScan(config, callback) {
|
||||||
|
let timestamp = process.hrtime();
|
||||||
|
async.waterfall([
|
||||||
|
// get files
|
||||||
|
function (waterfallCallback) {
|
||||||
|
util.readDirRecursive(config.input, config.format, waterfallCallback);
|
||||||
|
},
|
||||||
|
// display info, prompt user and create progressbar
|
||||||
|
function (files, waterfallCallback) {
|
||||||
|
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
|
||||||
|
cli.askForConfirmation('start scan now?', ['yes', 'y'], function (err) {
|
||||||
|
if (err) {
|
||||||
|
return waterfallCallback(err);
|
||||||
|
}
|
||||||
|
waterfallCallback(null, files, cli.createProgressBar(files.length));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// process each file
|
||||||
|
function (files, bar, waterfallCallback) {
|
||||||
|
let missing = [];
|
||||||
|
timestamp = process.hrtime();
|
||||||
|
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
||||||
|
extractMetadata(file, function (err, metadata) {
|
||||||
|
bar.tick();
|
||||||
|
if (err) {
|
||||||
|
return eachCallback(err);
|
||||||
|
}
|
||||||
|
if (!metadata.picture || metadata.picture.length === 0) {
|
||||||
|
missing.push(file);
|
||||||
|
}
|
||||||
|
eachCallback();
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return waterfallCallback(err);
|
||||||
|
}
|
||||||
|
waterfallCallback(null, missing, timestamp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
|
||||||
// extract metadata for further processing
|
// extract metadata for further processing
|
||||||
function extractMetadata(sourceFile, callback) {
|
function extractMetadata(source, callback) {
|
||||||
const stream = fs.createReadStream(sourceFile);
|
const stream = fs.createReadStream(source);
|
||||||
metadata(stream, function (err, metadata) {
|
metadata(stream, function (err, metadata) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
@ -156,7 +199,6 @@ function extractMetadata(sourceFile, callback) {
|
||||||
|
|
||||||
// api
|
// api
|
||||||
exports.batchConvert = batchConvert;
|
exports.batchConvert = batchConvert;
|
||||||
exports.convert = convert;
|
exports.batchArtwork = batchExtract;
|
||||||
exports.batchArtwork = batchArtwork;
|
exports.batchScan = batchScan;
|
||||||
exports.extractArtwork = extractArtwork;
|
|
||||||
exports.extractMetadata = extractMetadata;
|
exports.extractMetadata = extractMetadata;
|
|
@ -9,7 +9,7 @@ function printLogo() {
|
||||||
console.log(' | |__ __ _ __| |__ _ ___ _ _ /_\\ | \\/ |');
|
console.log(' | |__ __ _ __| |__ _ ___ _ _ /_\\ | \\/ |');
|
||||||
console.log(' | \'_ \\\/ _` \/ _` \/ _` / -_) \'_\/ _ \\| |\\/| |');
|
console.log(' | \'_ \\\/ _` \/ _` \/ _` / -_) \'_\/ _ \\| |\\/| |');
|
||||||
console.log(' |_.__\/\\__,_\\__,_\\__, \\___|_|\/_\/ \\_\\_| |_|');
|
console.log(' |_.__\/\\__,_\\__,_\\__, \\___|_|\/_\/ \\_\\_| |_|');
|
||||||
console.log(' |___/ ');
|
console.log(' |___/ \n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// display a confirmation prompt
|
// display a confirmation prompt
|
||||||
|
@ -46,11 +46,15 @@ function createProgressBar(total) {
|
||||||
|
|
||||||
// shutdown
|
// shutdown
|
||||||
function exit(err, timestamp) {
|
function exit(err, timestamp) {
|
||||||
|
let message = 'exiting'
|
||||||
|
if (timestamp) {
|
||||||
|
message += ' after ' + util.getTimeDiff(timestamp) + ' seconds';
|
||||||
|
}
|
||||||
|
console.log(message);
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
console.log('exiting after ' + util.getTimeDiff(timestamp) + ' seconds');
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ function batchSort(config, callback) {
|
||||||
},
|
},
|
||||||
// display info, prompt user and create progressbar
|
// display info, prompt user and create progressbar
|
||||||
function (files, waterfallCallback) {
|
function (files, waterfallCallback) {
|
||||||
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
|
console.log(files.length + ' files found after ' + getTimeDiff(timestamp) + ' seconds');
|
||||||
cli.askForConfirmation('start sorting now?', ['yes', 'y'], function (err) {
|
cli.askForConfirmation('start sorting now?', ['yes', 'y'], function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return waterfallCallback(err);
|
return waterfallCallback(err);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "badger-am",
|
"name": "badger-am",
|
||||||
"version": "0.5.4",
|
"version": "0.6.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "audio manager",
|
"description": "audio manager",
|
||||||
"author": "Daniel Sommer <daniel.sommer@velvettear.de>",
|
"author": "Daniel Sommer <daniel.sommer@velvettear.de>",
|
||||||
|
|
Loading…
Reference in a new issue