Parsing the STDERR output of node.js child_process line by line - node.js

I'm writing a simple online conversion tool using FFMPEG and Node.js. I'm trying to figure out how to parse each line of the conversion output received from FFMPEG and only display pertinent results client side in the browser. In my case I want the encoding time counter that FFMPEG spits out on the command line.
My function thus far is:
function metric(ffmpeg, res) {
ffmpeg.stdout.on('data', function(data) {
res.writeHead(200, {'content-type': 'text/html'});
res.write('received upload:\n\n');
console.log(data);
});
ffmpeg.stderr.on('data', function (data) {
var temp += data.toString();
var lines = temp.split('\n');
//for debugging purposes
for(var i = 0;i<lines.length;i++) {
console.log('this is line: ' + i + '----' + lines[i]);
}
res.write(lines);
});
ffmpeg.on('exit', function (code) {
console.log('child process exited with code ' + code);
res.end();
});
}
What this ends up returning is multiple arrays, each of which includes the data from the previous array as well as the next data chunk. For example, the function returns array 1:{0=>A, 1=>B}, array 2:{0=>A, 1=>B, 2=>C}, array 3:{0=>A, 1=>B, 2=>C, 3=>D}, and so on.
I'm quite new to Node so I'm probably missing something simple. Any guidance would be much appreciated!

This should do the job:
var buff = new Buffer(data);
console.log(buff.toString('utf8'));
For more information on buffers, here is a link to the doc: http://nodejs.org/docs/v0.4.2/api/buffers.html

Related

fluent-ffmpeg get codec data without specifying output

I am using fluent-ffmpeg node module for getting codec data from a file.
It works if I give an output but I was wondering if there is any option to run fluent-ffmpeg without giving to it an output.
This is what I am doing:
readStream.end(new Buffer(file.buffer));
var process = new ffmpeg(readStream);
process.on('start', function() {
console.log('Spawned ffmpeg');
}).on('codecData', function(data) {
//get recording duration
const duration = data.duration;
console.log(duration)
}).save('temp.flac');
As you can see I am saving the file to temp.flac so I can get the seconds duration of that file.
If you don't want to save the ffmpeg process result to a file, one thing that comes to mind is to redirect the command output to /dev/null.
In fact, as the owner of the fluent-ffmpeg repository said in one comment, there is no need to specify a real file name for the destination when using null format.
So, for example, something like that will work:
let process = new ffmpeg(readStream);
process
.addOption('-f', 'null') // set format to null
.on('start', function() {
console.log('Spawned ffmpeg');
})
.on('codecData', function(data) {
//get recording duration
let duration = data.duration;
console.log(duration)
})
.output('nowhere') // or '/dev/null' or something else
.run()
It remains a bit hacky, but we must set an output to avoid the "No output specified" error.
When no stream argument is present, the pipe() method returns a PassThrough stream, which you can pipe to somewhere else (or just listen to events on).
var command = ffmpeg('/path/to/file.avi')
.videoCodec('libx264')
.audioCodec('libmp3lame')
.size('320x240')
.on('error', function(err) {
console.log('An error occurred: ' + err.message);
})
.on('end', function() {
console.log('Processing finished !');
});
var ffstream = command.pipe();
ffstream.on('data', function(chunk) {
console.log('ffmpeg just wrote ' + chunk.length + ' bytes');
});

Unknown method process.openStdin()

I'm trying to pipe grep results into nodejs script. I've found, that I should receive data from process.stdin.
Also I've found several ways to work with stdin. But they are different and I can't find all information about it. I know four ways (first 3 start with var data = ""):
1) Most popular in search results
process.stdin.resume();
process.stdin.setEncoding( 'utf8' );
process.stdin.on('data', function(chunk) { data += chunk; });
process.stdin.on('end', function() { console.log('data: ' + data); });
2) Looks like the first one, but with unknown function process.openStdin()
var stdin = process.openStdin();
stdin.on('data', function(chunk) { data += chunk; });
stdin.on('end', function() { console.log('data: ' + data); });
3) In the documentation I've read that calling stdin.resume() changes stdin to 'old type'. So if we didn't called 'resume' - we can use 'readable' event
process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() { data += process.stdin.read(); });
process.stdin.on('end', function() { console.log('data: ' + data); });
4) Use module readline. It is very usefull as long as grep results are in mutiple lines and there I don't need to split received data by myself. But for a long time i couldn't understand why all information is piped to stdout directly. Then i i've found that we can pass empty object instead of process.stdout while creating interface and data wouldn't piped to output.
var readline = require('readline'),
//rl = readline.createInterface(process.stdin, process.stdout);
rl = readline.createInterface(process.stdin, {});
rl.on('line', function(data) { console.log('line: ' + data); });
5) My own variant. Use another module 'split' - it allows to read from stream and devide data into chuks by specified symbol (\r?\n by default). I used it to work with socket and as soon as stdin is also readable stream - we can use it here.
var split = require('split');
process.stdin.setEncoding('utf8');
process.stdin.pipe(split()).on('data', function(data) { console.log('line: ' + data); });
My question is "What is process.openStdin();????"
I've searched every page in google, but didn't found any documentation on this function!
Also while searching I've discovered, that official documentation for nodejs is ugly - not mentioned since which version methods are available, no detailed description on many objects/methods, no user comments. And this method (openStdin) - exists and works, but nowhere discribed! WTF???
While writing the question I've found the answer :)
It is in source code of nodejs:
process.openStdin = function() {
process.stdin.resume();
return process.stdin;
};
But I wonder, why is it not described in documentation? If it is a function for private use only, why is it used by many people, who wrote about working with stdin?

Node.js get all running processes

How can I get all current running process on my node server? I tried using ps-node (https://www.npmjs.com/package/ps-node) but failed to fetch the list.
I'm looking for something like the following command in C#:
// Get all processes running on the local computer.
Process[] localAll = Process.GetProcesses();
Is it possible?
Here is an example using the above mentioned forever tool, gnu awk and the built-in child_process node library:
var spawn = require('child_process').spawn,
forever = spawn('forever', ['list', '--plain']),
awk = spawn('awk', ['NR>2{print $4,$5,$6,$7,"\t",$9}']);
forever.stdout.on('data', function (data) {
awk.stdin.write(data);
});
forever.stderr.on('data', function (data) {
console.log('forever stderr: ' + data);
});
forever.on('close', function (code) {
if (code !== 0) {
console.log('forever process exited with code ' + code);
}
awk.stdin.end();
});
awk.stdout.on('data', function (data) {
// data is your result as Buffer
// print data as string
console.log('' + data);
});
awk.stderr.on('data', function (data) {
console.log('awk stderr: ' + data);
});
awk.on('close', function (code) {
if (code !== 0) {
console.log('awk process exited with code ' + code);
}
});
What's happening here, basically is:
$ forever list --plain | awk '{NR>2{print $4,$5,$6,$7,"\t",$9}}'
Of course, the variables awk prints depend on the forever list output... To test the correct solution I would start from printing $0 to get the whole output, then trim it down such that it reports only the informations you need.

Node.js stream data from a terminal command to the client

There were already a few questions here about node.js executing commands and outputting the data, but I still can't get this working. What I want is that using node.js I want to execute a python script that runs for a long time and produces some intermediate outputs. I want to stream these outputs to the client as soon as they are produced. I have tried the following, but what I get is that I get the whole output only once the command has finished. How can I make it pass on the data into the socket in real time? Thanks.
function run_cmd(cmd, args) {
var spawn = require('child_process').spawn,
child = spawn(cmd, args);
return child;
}
io.sockets.on('connection', function (socket) {
var foo = new run_cmd('python', ['test.py']);
foo.stdout.setEncoding('utf-8');
foo.stdout.on('data', function(data) {
console.log('sending data');
io.sockets.emit('terminal', {output: data});;
});
);
all your node.js code is okay.your code sends data only once because your code gets data only once.
The point is puts or print commands are not enough to trigger foo.stdout.on
try adding '$stdout.flush' at the point you want to send chunk in ruby code.
You need to order explicitly to output data.
here is my test code.
js
var spawn = require('child_process').spawn;
var cmd = spawn('ruby', ['testRuby.rb']);
var counter = 0;
cmd.stdout.on('data', function(data) {
counter ++;
console.log('stdout: ' + data);
});
cmd.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
cmd.on('exit', function(code) {
console.log('exit code: ' + code);
console.log(counter);
});
testRuby.rb
def execute_each_sec(sleep_sec)
yield
sleep sleep_sec
end
5.times do
execute_each_sec(1) do ||
puts "CurrentTime:#{Time.now}"
$stdout.flush
end
end
as you can see I'm calling $stdout.flush to output data explicitly in testRuby.rb.
if I remove that,node.js won't get anything until execution of testRuby.rb's finished.
edited
lol my bad. I used ruby instead of python.
in the case of python, use sys.stdout.flush() like svkk says
Edit:
In python you can also use -u flag to force it to flush after each print.

Having trouble understanding node.js listeners

I'm working on two node.js tutorials at the moment and while I understand what is going on within each tutorial, I clearly don't understand what's going on that well.
The following code listens for "data" events and then adds new chunks of data to a variable named postData. Another listener sends this data along with other stuff to my route.js file.
request.addListener("data", function (postDataChunk) {
postData += postDataChunk;
console.log("Received POST data chunk '" + postDataChunk + "'.");
});
request.addListener("end", function () {
route(handle, pathname, response, postData);
});
The following code creates a variable, tailChild, that spawns the shell command 'tail' on my system log and then attempts to add this data to my postData variable:
var spawn = require('child_process').spawn;
var tail_child = spawn('tail', ['-f', '/var/log/system.log']);
tail_child.stdout.on('data', function (data) {
postData += data;
console.log("TAIL READING: " + data);
});
tail_child.stdout.on('end', function () {
route(handle, pathname, response, postData);
});
Now my console is updated in realtime with system.log data but my browser times out with a "No data received error."
I've tried tweaking the code above to figure what is going wrong and as near as I can tell node is telling me that var data is null so it is adding nothing to var postData. This doesn't make sense to me since console.log("TAIL READING: " + data) gives me the results of spawn('tail', ['-f', '/var/log/system.log']) in my terminal window. Clearly var data is not null.
Edit:
Here's a pastebin link to my server.js code
tail -f won't trigger the end callback so you never respond to the user.

Resources