132 lines
3.9 KiB
JavaScript
Executable file
132 lines
3.9 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
// requirements
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const async = require('async');
|
|
const commander = require('commander');
|
|
const recursive = require('recursive-readdir');
|
|
const app = require('./package.json');
|
|
const audio = require('./lib/audio');
|
|
const util = require('./lib/util');
|
|
const cli = require('./lib/cli');
|
|
|
|
// generate timestamp
|
|
const start = process.hrtime();
|
|
|
|
badger();
|
|
|
|
// "main"
|
|
function badger() {
|
|
cli.printLogo();
|
|
run();
|
|
}
|
|
|
|
// start from command lines
|
|
function run() {
|
|
// general options
|
|
commander
|
|
.version(app.version)
|
|
.usage('[options] <command>')
|
|
.option('-c, --concurrency <n>', 'specify concurrency level', os.cpus().length);
|
|
// conversion
|
|
commander
|
|
.command('convert <input> <output>')
|
|
.description('convert .flac to .mp3 files')
|
|
.option('-b, --bitrate <n>', 'specify conversion bitrate', 320)
|
|
.action(convert);
|
|
// sort
|
|
commander
|
|
.command('sort <input> <output>')
|
|
.description('sort audio files by tags')
|
|
.option('-f, --format <type>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
|
.action(sort);
|
|
// artwork
|
|
commander
|
|
.command('artwork <input>')
|
|
.description('extract cover artwork')
|
|
.option('-f, --format <type>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
|
.action(artwork);
|
|
// parse command line arguments
|
|
commander.parse(process.argv);
|
|
}
|
|
|
|
// create config object
|
|
function getConfig(input, output, options, commander) {
|
|
return {
|
|
input: path.normalize(input),
|
|
output: path.normalize(output),
|
|
concurrency: commander.concurrency || os.cpus().length,
|
|
bitrate: options.bitrate || 320,
|
|
format: options.format || '.flac'
|
|
}
|
|
}
|
|
|
|
// convert files
|
|
function convert(input, output, options) {
|
|
audio.batchConvert(getConfig(input, output, options, commander), function (err) {
|
|
cli.exit(err);
|
|
});
|
|
}
|
|
|
|
// sort files
|
|
function sort(input, output, options) {
|
|
util.batchSort(getConfig(input, output, options, commander), function (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
|
|
function artwork(input, options) {
|
|
async.waterfall([
|
|
function (asyncCallback) {
|
|
recursive(input, [ignoreFilter], asyncCallback);
|
|
},
|
|
function (files, asyncCallback) {
|
|
console.log(files.length + ' \'' + options.format + '\' files found');
|
|
// 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;
|
|
}
|
|
} |