extendended logging, minor fixes
This commit is contained in:
parent
5d74221deb
commit
db6b470694
5 changed files with 69 additions and 33 deletions
33
badger-am.js
33
badger-am.js
|
@ -10,19 +10,11 @@ const audio = require('./lib/audio');
|
||||||
const util = require('./lib/util');
|
const util = require('./lib/util');
|
||||||
const cli = require('./lib/cli');
|
const cli = require('./lib/cli');
|
||||||
|
|
||||||
// generate timestamp
|
|
||||||
const start = process.hrtime();
|
|
||||||
|
|
||||||
badger();
|
badger();
|
||||||
|
|
||||||
// "main"
|
// main application
|
||||||
function badger() {
|
function badger() {
|
||||||
cli.printLogo();
|
cli.printLogo();
|
||||||
run();
|
|
||||||
}
|
|
||||||
|
|
||||||
// start from command lines
|
|
||||||
function run() {
|
|
||||||
// general options
|
// general options
|
||||||
commander
|
commander
|
||||||
.version(app.version)
|
.version(app.version)
|
||||||
|
@ -38,14 +30,20 @@ function run() {
|
||||||
commander
|
commander
|
||||||
.command('sort <input> <output>')
|
.command('sort <input> <output>')
|
||||||
.description('sort audio files by tags')
|
.description('sort audio files by tags')
|
||||||
.option('-f, --format <type>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
||||||
.action(sort);
|
.action(sort);
|
||||||
// artwork
|
// artwork
|
||||||
commander
|
commander
|
||||||
.command('artwork <input>')
|
.command('artwork <input>')
|
||||||
.description('extract cover artwork')
|
.description('extract cover artwork')
|
||||||
.option('-f, --format <type>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
||||||
.action(artwork);
|
.action(artwork);
|
||||||
|
// scan
|
||||||
|
commander
|
||||||
|
.command('scan <input>')
|
||||||
|
.description('scan audio files for missing cover artwork')
|
||||||
|
.option('-f, --format <format>', 'specify audio format (\'flac\', \'mp3\')', '.flac')
|
||||||
|
.action(scan);
|
||||||
// parse command line arguments
|
// parse command line arguments
|
||||||
commander.parse(process.argv);
|
commander.parse(process.argv);
|
||||||
}
|
}
|
||||||
|
@ -58,8 +56,8 @@ function convert(input, output, options) {
|
||||||
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) {
|
}, function (err, time) {
|
||||||
cli.exit(err);
|
cli.exit(err, time);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +69,7 @@ function sort(input, output, options) {
|
||||||
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) {
|
}, function (err, time) {
|
||||||
cli.exit(err);
|
cli.exit(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -82,7 +80,12 @@ function artwork(input, options) {
|
||||||
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) {
|
}, function (err, time) {
|
||||||
cli.exit(err);
|
cli.exit(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scan files
|
||||||
|
function scan(input, options) {
|
||||||
|
|
||||||
|
}
|
24
lib/audio.js
24
lib/audio.js
|
@ -10,6 +10,7 @@ const cli = require('./cli');
|
||||||
|
|
||||||
// convert all files in input directory
|
// convert all files in input directory
|
||||||
function batchConvert(config, callback) {
|
function batchConvert(config, callback) {
|
||||||
|
let timestamp = process.hrtime();
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
// get files
|
// get files
|
||||||
function (waterfallCallback) {
|
function (waterfallCallback) {
|
||||||
|
@ -17,7 +18,8 @@ function batchConvert(config, callback) {
|
||||||
},
|
},
|
||||||
// display info, prompt user and create progressbar
|
// display info, prompt user and create progressbar
|
||||||
function (files, waterfallCallback) {
|
function (files, waterfallCallback) {
|
||||||
cli.askForConfirmation(files.length + ' files found.\nstart conversion now?', ['yes', 'y'], function (err) {
|
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
|
||||||
|
cli.askForConfirmation('start conversion now?', ['yes', 'y'], function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return waterfallCallback(err);
|
return waterfallCallback(err);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +28,7 @@ function batchConvert(config, callback) {
|
||||||
},
|
},
|
||||||
// process each file
|
// process each file
|
||||||
function (files, bar, waterfallCallback) {
|
function (files, bar, waterfallCallback) {
|
||||||
|
timestamp = process.hrtime();
|
||||||
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
||||||
convert(file, config, function (err) {
|
convert(file, config, function (err) {
|
||||||
bar.tick();
|
bar.tick();
|
||||||
|
@ -34,7 +37,12 @@ function batchConvert(config, callback) {
|
||||||
}
|
}
|
||||||
eachCallback();
|
eachCallback();
|
||||||
});
|
});
|
||||||
}, waterfallCallback);
|
}, function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
return waterfallCallback(err);
|
||||||
|
}
|
||||||
|
waterfallCallback(null, timestamp)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
}
|
}
|
||||||
|
@ -75,6 +83,7 @@ function convert(source, config, callback) {
|
||||||
|
|
||||||
//
|
//
|
||||||
function batchArtwork(config, callback) {
|
function batchArtwork(config, callback) {
|
||||||
|
let timestamp = process.hrtime();
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
// get files
|
// get files
|
||||||
function (waterfallCallback) {
|
function (waterfallCallback) {
|
||||||
|
@ -82,7 +91,8 @@ function batchArtwork(config, callback) {
|
||||||
},
|
},
|
||||||
// display info, prompt user and create progressbar
|
// display info, prompt user and create progressbar
|
||||||
function (files, waterfallCallback) {
|
function (files, waterfallCallback) {
|
||||||
cli.askForConfirmation(files.length + ' files found.\nstart artwork extraction now?', ['yes', 'y'], function (err) {
|
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
|
||||||
|
cli.askForConfirmation('start artwork extraction now?', ['yes', 'y'], function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return waterfallCallback(err);
|
return waterfallCallback(err);
|
||||||
}
|
}
|
||||||
|
@ -91,6 +101,7 @@ function batchArtwork(config, callback) {
|
||||||
},
|
},
|
||||||
// process each file
|
// process each file
|
||||||
function (files, bar, waterfallCallback) {
|
function (files, bar, waterfallCallback) {
|
||||||
|
timestamp = process.hrtime();
|
||||||
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
||||||
extractArtwork(file, function (err) {
|
extractArtwork(file, function (err) {
|
||||||
bar.tick();
|
bar.tick();
|
||||||
|
@ -99,7 +110,12 @@ function batchArtwork(config, callback) {
|
||||||
}
|
}
|
||||||
eachCallback();
|
eachCallback();
|
||||||
});
|
});
|
||||||
}, waterfallCallback);
|
}, function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
return waterfallCallback(err);
|
||||||
|
}
|
||||||
|
waterfallCallback(null, timestamp);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// requirements
|
// requirements
|
||||||
const progress = require('progress');
|
const progress = require('progress');
|
||||||
const readline = require('readline');
|
const readline = require('readline');
|
||||||
|
const util = require('./util');
|
||||||
|
|
||||||
// print logo
|
// print logo
|
||||||
function printLogo() {
|
function printLogo() {
|
||||||
|
@ -29,7 +30,7 @@ function askForConfirmation(message, confirms, callback) {
|
||||||
line.question(message + '\n', function (answer) {
|
line.question(message + '\n', function (answer) {
|
||||||
line.close();
|
line.close();
|
||||||
if (confirms.indexOf(answer) === -1) {
|
if (confirms.indexOf(answer) === -1) {
|
||||||
return callback('wrong input: \'' + answer + '\'');
|
return callback('aborted by user, answered \'' + answer + '\'');
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -44,13 +45,12 @@ function createProgressBar(total) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shutdown
|
// shutdown
|
||||||
function exit(err, start) {
|
function exit(err, timestamp) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
const diff = process.hrtime(start);
|
console.log('exiting after ' + util.getTimeDiff(timestamp) + ' seconds');
|
||||||
console.log('exiting after ' + ((diff[0] + (diff[1] / 1000000)) / 1000).toFixed(2) + ' seconds');
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
33
lib/util.js
33
lib/util.js
|
@ -9,6 +9,7 @@ const audio = require('./audio');
|
||||||
|
|
||||||
// move all files from input to output directory
|
// move all files from input to output directory
|
||||||
function batchSort(config, callback) {
|
function batchSort(config, callback) {
|
||||||
|
let timestamp = process.hrtime();
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
// get files
|
// get files
|
||||||
function (waterfallCallback) {
|
function (waterfallCallback) {
|
||||||
|
@ -16,15 +17,17 @@ function batchSort(config, callback) {
|
||||||
},
|
},
|
||||||
// display info, prompt user and create progressbar
|
// display info, prompt user and create progressbar
|
||||||
function (files, waterfallCallback) {
|
function (files, waterfallCallback) {
|
||||||
cli.askForConfirmation(files.length + ' files found.\nstart sorting now?', ['yes', 'y'], function (err) {
|
console.log(files.length + ' files found after ' + util.getTimeDiff(timestamp) + ' seconds');
|
||||||
|
cli.askForConfirmation('start sorting now?', ['yes', 'y'], function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return waterfallCallback(err);
|
return waterfallCallback(err);
|
||||||
}
|
}
|
||||||
waterfallCallback(null, files, cli.createProgressBar(files.length));
|
waterfallCallback(null, files, cli.createProgressBar(files.length));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// process each file
|
// process each file
|
||||||
function (files, bar, waterfallCallback) {
|
function (files, bar, waterfallCallback) {
|
||||||
|
timestamp = process.hrtime();
|
||||||
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
async.eachLimit(files, config.concurrency, function (file, eachCallback) {
|
||||||
moveFile(file, config, function (err) {
|
moveFile(file, config, function (err) {
|
||||||
bar.tick();
|
bar.tick();
|
||||||
|
@ -33,7 +36,12 @@ function batchSort(config, callback) {
|
||||||
}
|
}
|
||||||
eachCallback();
|
eachCallback();
|
||||||
})
|
})
|
||||||
}, waterfallCallback);
|
}, function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
return waterfallCallback(err);
|
||||||
|
}
|
||||||
|
waterfallCallback(null, timestamp);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
}
|
}
|
||||||
|
@ -87,12 +95,12 @@ function getPathByMetadata(source, output, metadata, callback) {
|
||||||
tmp = metadata.albumartist[counter];
|
tmp = metadata.albumartist[counter];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filePath = path.join(filePath, replaceSpecialChars(tmp.trim()));
|
filePath = path.join(filePath, replaceIllegalChars(tmp.trim()));
|
||||||
} else {
|
} else {
|
||||||
filePath = path.join(filePath, replaceSpecialChars(metadata.artist[0].trim()));
|
filePath = path.join(filePath, replaceIllegalChars(metadata.artist[0].trim()));
|
||||||
}
|
}
|
||||||
if (metadata.album) {
|
if (metadata.album) {
|
||||||
filePath = path.join(filePath, replaceSpecialChars(metadata.album.trim()));
|
filePath = path.join(filePath, replaceIllegalChars(metadata.album.trim()));
|
||||||
}
|
}
|
||||||
// define filename
|
// define filename
|
||||||
let fileName = '';
|
let fileName = '';
|
||||||
|
@ -113,7 +121,7 @@ function getPathByMetadata(source, output, metadata, callback) {
|
||||||
fileName += metadata.title.trim();
|
fileName += metadata.title.trim();
|
||||||
}
|
}
|
||||||
// append extension
|
// append extension
|
||||||
fileName += replaceSpecialChars(path.extname(source)).trim();
|
fileName += replaceIllegalChars(path.extname(source)).trim();
|
||||||
// join directory and name
|
// join directory and name
|
||||||
callback(null, path.join(filePath, fileName));
|
callback(null, path.join(filePath, fileName));
|
||||||
}
|
}
|
||||||
|
@ -126,12 +134,14 @@ function frontFill(string, fill, length) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceSpecialChars(string) {
|
// replace illegal characters
|
||||||
|
function replaceIllegalChars(string) {
|
||||||
return string.replace(/[/\\:*?"<>|]/g, '-');
|
return string.replace(/[/\\:*?"<>|]/g, '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
// list files in directory
|
// list files in directory
|
||||||
function readDirRecursive(where, extension, callback) {
|
function readDirRecursive(where, extension, callback) {
|
||||||
|
console.log('getting list of \'' + extension + '\' files in directory \'' + where + '\' ...');
|
||||||
if (extension.indexOf('.') !== 0) {
|
if (extension.indexOf('.') !== 0) {
|
||||||
extension = '.' + extension;
|
extension = '.' + extension;
|
||||||
}
|
}
|
||||||
|
@ -141,9 +151,16 @@ function readDirRecursive(where, extension, callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get difference to timestamp
|
||||||
|
function getTimeDiff(timestamp) {
|
||||||
|
const diff = process.hrtime(timestamp);
|
||||||
|
return (diff[0] + diff[1] / 1e9).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
// api
|
// api
|
||||||
exports.batchSort = batchSort;
|
exports.batchSort = batchSort;
|
||||||
exports.moveFile = moveFile;
|
exports.moveFile = moveFile;
|
||||||
exports.getPathByMetadata = getPathByMetadata;
|
exports.getPathByMetadata = getPathByMetadata;
|
||||||
exports.frontFill = frontFill;
|
exports.frontFill = frontFill;
|
||||||
exports.readDirRecursive = readDirRecursive;
|
exports.readDirRecursive = readDirRecursive;
|
||||||
|
exports.getTimeDiff = getTimeDiff;
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "badger-am",
|
"name": "badger-am",
|
||||||
"version": "0.5.3",
|
"version": "0.5.4",
|
||||||
"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