// requirements const fs = require('fs'); const path = require('path'); const async = require('async'); const metadata = require('musicmetadata'); const ffmpeg = require('fluent-ffmpeg'); const fse = require('fs-extra'); const util = require('./util'); // convert file to mp3 at specified bitrate function convert(input, output, bitrate, callback) { output = path.join(path.dirname(output), path.basename(output, path.extname(output)) + '.mp3'); async.series([ function (asyncCallback) { fse.mkdirs(path.dirname(output), asyncCallback); }, function (asyncCallback) { ffmpeg(path.normalize(input)).audioCodec('libmp3lame').audioBitrate(bitrate).save(output) .on('error', function (err) { return asyncCallback(err); }) .on('end', function () { asyncCallback(); }); } ], function (err, results) { if (err) { return callback(err); } callback(); }); } // extract cover artwork function extractArtwork(sourceFile, callback) { async.waterfall([ function (asyncCallback) { extractMetadata(sourceFile, asyncCallback); }, function (metadata, asyncCallback) { metadata.picture.forEach(function (picture) { const pic = path.join(path.dirname(sourceFile), path.basename(sourceFile, path.extname(sourceFile)) + '.' + picture.format); const stream = fs.createWriteStream(pic); stream.write(picture.data); stream.end(); asyncCallback(); }); } ], function (err, result) { if (err) { return callback(err); } callback(); }); } // extract metadata for further processing function extractMetadata(sourceFile, callback) { const stream = fs.createReadStream(sourceFile); metadata(stream, function (err, metadata) { if (err) { return callback(err); } stream.close(); callback(null, metadata); }); } // api exports.convert = convert; exports.extractArtwork = extractArtwork; exports.extractMetadata = extractMetadata;