Harsh Wardhan Harsh Wardhan - 1 month ago 15
reST (reStructuredText) Question

How to pass a video file as input to a child process in NodeJS and receive frames/images as output?

I have written a code in OpenCV C++ which takes a video and a timestamp (in HH:MM:SS format) as input, from the command line, and detects faces in that frame. The detected faces are cropped and written as PNG files.

$ ./executable video.mp4 00:00:01


Now I want to build a web API for the
executable
in NodeJS. I have used
child_process.spawn
along with the command line arguments. The application runs without any error but I'm not getting the cropped images as output. It seems my app is either not able to pass the input video to the
executable
or not able to read the output from it. This is my first NodeJS application. Here's my code.

/**
* app.js
* make sure to install express (npm install express)
* and place the executable beside this file
* or set executablePath to the correct path.
* run the app and open 'http://0.0.0.0:3000' in your browser.
*/

var child_process = require('child_process');
var path = require('path');
var express = require('express');
var app = express();

var executable = null;

app.get('/', function (req, res) {

const args = process.argv;
console.log(args);
//console.log(process.argv[3]);

if (process.argv.length <= 3) {
console.log("Usage: nodemon " + __filename + " <path/to/video> <HH:MM:SS>");
process.exit(-1);
}

if (executable !== null) {
res.end('executable is already running.');
return;
}

var executablePath = path.join(__dirname, './executable');
executable = child_process.spawn(executablePath, [process.argv[2], process.argv[3]]);

executable.on('exit', function (signal, code) {
console.log('executable exited with signal: %s and code: %d', signal, code);
executable = null;
});

res.end('Done.');
});

app.listen(3000);
console.log('Listening on port 3000');


I'm running it as

$ nodemon app.js video.mp4 00:00:01


I also need to know how I can pass the parameters
video.mp4
and
00:00:01
from the API itself.

Answer

I figured out the solution myself. I need to add {stdio: 'inherit'} option while spawning the child process. Here's the final code:

/**
* app.js
* make sure to install express (npm install express)
* and place the executable beside this file
* or set executablePath to the correct path.
* run the app and open 'localhost:3000/?vid=<path to video file>&tstamp=<timestamp in HH:MM:SS format>' in your browser.
*/

var child_process = require('child_process');
var path = require('path');
var express = require('express');
var app = express();
var fs = require('fs');

var executable = null;

app.get('/', function (req, res) {

if (executable !== null) {
res.end('executable is already running.');
return;
}

var video = req.param('vid');
var timestamp = req.param('tstamp');

var executablePath = path.join(__dirname, './executable2');

executable = child_process.spawn(executablePath, [video, timestamp], {stdio: 'inherit'});

executable.on('exit', function (signal, code) {
console.log('executable exited with signal: %s and code: %d', signal, code);
executable = null;
});

res.end('Done.');
});

app.listen(3000);
console.log('Listening on port 3000');

Thereafter, run the app as

$ nodemon app.js

and open the following link in the browser

localhost:3000/?vid=<path to video file>&tstamp=<timestamp in HH:MM:SS format>

It takes the video file and the timestamp from the url itself, no need to provide these parameters from the terminal while running the app.