added extract images and other changes
This commit is contained in:
parent
4ac2c5c515
commit
7f5090a13e
|
@ -7,7 +7,6 @@ const logger = require('./utils/logger.js');
|
|||
const constants = require('./constants.js');
|
||||
|
||||
fileSizeLimit = constants.fileSizeLimit;
|
||||
port = 3000;
|
||||
timeout = 3600000;
|
||||
|
||||
// catch SIGINT and SIGTERM and exit
|
||||
|
@ -45,7 +44,7 @@ require('express-readme')(app, {
|
|||
});
|
||||
|
||||
|
||||
const server = app.listen(port, function() {
|
||||
const server = app.listen(constants.serverPort, function() {
|
||||
let host = server.address().address;
|
||||
let port = server.address().port;
|
||||
logger.info('listening http://'+host+':'+port)
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
|
||||
exports.fileSizeLimit = parseInt(process.env.FILE_SIZE_LIMIT_BYTES || "536870912") //536870912 = 512MB
|
||||
exports.fileSizeLimit = parseInt(process.env.FILE_SIZE_LIMIT_BYTES || "536870912"); //536870912 = 512MB
|
||||
exports.defaultFFMPEGProcessPriority=10;
|
||||
exports.serverPort = 3000;//port to listen, NOTE: if using Docker/Kubernetes this port may not be the one clients are using
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"express-list-endpoints": "4.0.1",
|
||||
"fs": "0.0.1-security",
|
||||
"unique-filename": "^1.1.1",
|
||||
"winston": "^3.2.1"
|
||||
"winston": "^3.2.1",
|
||||
"archiver": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^6.8.0",
|
||||
|
|
|
@ -2,6 +2,8 @@ var express = require('express')
|
|||
const fs = require('fs');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
|
||||
const constants = require('../constants.js');
|
||||
|
||||
var router = express.Router()
|
||||
const logger = require('../utils/logger.js')
|
||||
|
||||
|
@ -76,25 +78,24 @@ function convert(req,res,next) {
|
|||
//ffmpeg processing... converting file...
|
||||
let ffmpegConvertCommand = ffmpeg(savedFile);
|
||||
ffmpegConvertCommand
|
||||
.renice(15)
|
||||
.renice(constants.defaultFFMPEGProcessPriority)
|
||||
.outputOptions(ffmpegParams.outputOptions)
|
||||
.on('error', function(err) {
|
||||
logger.error(`${err}`);
|
||||
fs.unlinkSync(savedFile);
|
||||
utils.deleteFile(savedFile);
|
||||
res.writeHead(500, {'Connection': 'close'});
|
||||
res.end(JSON.stringify({error: `${err}`}));
|
||||
})
|
||||
.on('end', function() {
|
||||
fs.unlinkSync(savedFile);
|
||||
utils.deleteFile(savedFile);
|
||||
logger.debug(`starting download to client ${savedFile}`);
|
||||
|
||||
res.download(outputFile, null, function(err) {
|
||||
if (err) {
|
||||
logger.error(`download ${err}`);
|
||||
}
|
||||
logger.debug(`deleting ${outputFile}`);
|
||||
if (fs.unlinkSync(outputFile)) {
|
||||
logger.debug(`deleted ${outputFile}`);
|
||||
else {
|
||||
utils.deleteFile(`${outputFile}`);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
var express = require('express')
|
||||
const fs = require('fs');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const uniqueFilename = require('unique-filename');
|
||||
var archiver = require('archiver');
|
||||
|
||||
const constants = require('../constants.js');
|
||||
|
||||
var router = express.Router()
|
||||
const logger = require('../utils/logger.js')
|
||||
const utils = require('../utils/utils.js')
|
||||
|
||||
|
||||
//routes for /video/extract
|
||||
|
@ -11,25 +16,193 @@ const logger = require('../utils/logger.js')
|
|||
//extracts images from vide
|
||||
router.post('/audio', function (req, res,next) {
|
||||
|
||||
res.locals.conversion="audio"
|
||||
res.locals.format="wav"
|
||||
res.locals.extract="audio"
|
||||
return extract(req,res,next);
|
||||
});
|
||||
|
||||
router.post('/images', function (req, res,next) {
|
||||
|
||||
res.locals.conversion="images"
|
||||
res.locals.format="png"
|
||||
res.locals.extract="images"
|
||||
return extract(req,res,next);
|
||||
});
|
||||
|
||||
router.get('/download/:filename', function (req, res,next) {
|
||||
//download extracted image
|
||||
let filename = req.params.filename;
|
||||
let deleteFile = req.query.delete || "true";
|
||||
|
||||
let file = `/tmp/${filename}`
|
||||
logger.debug(`starting download to client ${file}`);
|
||||
res.download(file, filename, function(err) {
|
||||
if (err) {
|
||||
logger.error(`download ${err}`);
|
||||
}
|
||||
else
|
||||
{
|
||||
//delete file if no delete=no query parameter
|
||||
if (deleteFile === "true" || deleteFile === "yes")
|
||||
{
|
||||
utils.deleteFile(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// extract audio or images from video
|
||||
function extract(req,res,next) {
|
||||
let msg="Not yet implemented.";
|
||||
logger.error(msg);
|
||||
let err = new Error(msg);
|
||||
err.statusCode = 500;
|
||||
next(err);
|
||||
let extract = res.locals.extract;
|
||||
logger.debug(`extract ${extract}`);
|
||||
|
||||
let fps = req.query.fps || 1;
|
||||
//compress = zip or gzip
|
||||
let compress = req.query.compress || "none";
|
||||
let ffmpegParams ={};
|
||||
var format = "png";
|
||||
if (extract === "images"){
|
||||
format = "png"
|
||||
ffmpegParams.outputOptions=[
|
||||
`-vf fps=${fps}`
|
||||
];
|
||||
}
|
||||
if (extract === "audio"){
|
||||
format = "wav"
|
||||
ffmpegParams.outputOptions=[
|
||||
`-ac 1` ,
|
||||
`-f ${format}`
|
||||
];
|
||||
}
|
||||
|
||||
ffmpegParams.extension = format;
|
||||
|
||||
let savedFile = res.locals.savedFile;
|
||||
|
||||
var outputFile = uniqueFilename('/tmp/') ;
|
||||
logger.debug(`outputFile ${outputFile}`);
|
||||
var uniqueFileNamePrefix = outputFile.replace("/tmp/","");
|
||||
logger.debug(`uniqueFileNamePrefix ${uniqueFileNamePrefix}`);
|
||||
|
||||
//ffmpeg processing... converting file...
|
||||
var ffmpegCommand = ffmpeg(savedFile);
|
||||
ffmpegCommand = ffmpegCommand
|
||||
.renice(constants.defaultFFMPEGProcessPriority)
|
||||
.outputOptions(ffmpegParams.outputOptions)
|
||||
.on('error', function(err) {
|
||||
logger.error(`${err}`);
|
||||
utils.deleteFile(savedFile);
|
||||
res.writeHead(500, {'Connection': 'close'});
|
||||
res.end(JSON.stringify({error: `${err}`}));
|
||||
})
|
||||
|
||||
if (extract === "images"){
|
||||
ffmpegCommand
|
||||
.output(`${outputFile}-%04d.png`)
|
||||
.on('end', function() {
|
||||
logger.debug(`ffmpeg process ended`);
|
||||
|
||||
utils.deleteFile(savedFile)
|
||||
|
||||
//read extracted files
|
||||
var files = fs.readdirSync('/tmp/').filter(fn => fn.startsWith(uniqueFileNamePrefix));
|
||||
|
||||
if (compress === "zip" || compress === "gzip")
|
||||
{
|
||||
//do zip or tar&gzip of all images and download file
|
||||
var archive = null;
|
||||
var extension = "";
|
||||
if (compress === "gzip") {
|
||||
archive = archiver('tar', {
|
||||
gzip: true,
|
||||
zlib: { level: 9 } // Sets the compression level.
|
||||
});
|
||||
extension = "tar.gz";
|
||||
}
|
||||
else {
|
||||
archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Sets the compression level.
|
||||
});
|
||||
extension = "zip";
|
||||
}
|
||||
|
||||
let compressFileName = `${uniqueFileNamePrefix}.${extension}`
|
||||
let compressFilePath = `/tmp/${compressFileName}`
|
||||
logger.debug(`starting ${compress} process ${compressFilePath}`);
|
||||
var compressFile = fs.createWriteStream(compressFilePath);
|
||||
|
||||
archive.on('error', function(err) {
|
||||
return next(err);
|
||||
});
|
||||
|
||||
// pipe archive data to the output file
|
||||
archive.pipe(compressFile);
|
||||
|
||||
// add files to archive
|
||||
for (var i=0; i < files.length; i++) {
|
||||
var file = `/tmp/${files[i]}`;
|
||||
archive.file(file, {name: files[i]});
|
||||
}
|
||||
|
||||
// listen for all archive data to be written
|
||||
// 'close' event is fired only when a file descriptor is involved
|
||||
compressFile.on('close', function() {
|
||||
logger.debug(`${compressFileName}: ${archive.pointer()} total bytes`);
|
||||
logger.debug('archiver has been finalized and the output file descriptor has closed.');
|
||||
|
||||
// delete all images
|
||||
for (var i=0; i < files.length; i++) {
|
||||
var file = `/tmp/${files[i]}`;
|
||||
utils.deleteFile(file);
|
||||
}
|
||||
|
||||
//return tar.gz
|
||||
logger.debug(`starting download to client ${compressFilePath}`);
|
||||
res.download(compressFilePath, compressFileName, function(err) {
|
||||
if (err) {
|
||||
logger.error(`download gzip error: ${err}`);
|
||||
return next(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug(`download complete ${compressFilePath}`);
|
||||
utils.deleteFile(compressFilePath);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
// Wait for streams to complete
|
||||
archive.finalize();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//return JSON list of extracted images
|
||||
|
||||
logger.debug(`output files in /tmp`);
|
||||
var responseJson = {};
|
||||
responseJson["totalfiles"] = files.length;
|
||||
responseJson["description"] = "Extracted image files and URLs to download them. By default, downloading image also deletes the image from server. Note port in the URL may be different if server is running on Docker/Kubernetes.";
|
||||
var filesArray=[];
|
||||
for (var i=0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
logger.debug("file: " + file);
|
||||
var fileJson={};
|
||||
fileJson["name"] = file;
|
||||
fileJson[`url`] = `${req.protocol}://${req.hostname}:${constants.serverPort}${req.baseUrl}/download/${file}`;
|
||||
filesArray.push(fileJson);
|
||||
}
|
||||
responseJson["files"] = filesArray;
|
||||
res.status(200).send(responseJson);
|
||||
|
||||
}
|
||||
})
|
||||
.run();
|
||||
// .save(outputFile);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ router.use(function (req, res,next) {
|
|||
});
|
||||
busboy.on('finish', function() {
|
||||
if (hitLimit) {
|
||||
fs.unlinkSync(savedFile);
|
||||
utils.deleteFile(savedFile);
|
||||
return;
|
||||
}
|
||||
logger.debug(`upload complete. file: ${fileName}`)
|
||||
|
|
12
src/utils/utils.js
Normal file
12
src/utils/utils.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
const fs = require('fs');
|
||||
const logger = require('./logger.js')
|
||||
|
||||
|
||||
function deleteFile (filepath) {
|
||||
fs.unlinkSync(filepath);
|
||||
logger.debug(`deleted ${filepath}`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deleteFile
|
||||
}
|
Loading…
Reference in New Issue
Block a user