Greyhammer
Greyhammer

Reputation: 183

running ffmpeg via nodejs error

I'm trying to run ffmpeg from node, and I'm getting an error. Here is the code

var exec = require('child_process').exec;

var cmd = '/home/ubuntu/bin/ffmpeg -i /home/ubuntu/input.flv -s 640x480 -y -codec:a aac -b:a 44.1k -r 15 -b:v 1000k -codec:v h264 -f mp4 /home/ubuntu/output.mp4';

exec(cmd, function(err, stdout, stderr) {
    if (err) console.log('err:\n' + err);
    if (stderr) console.log('stderr:\n' + stderr);
    console.log('stdout:\n' + stdout);
});

When I run this node script, I get the following errors:

err:
Error: Command failed: /home/ubuntu/bin/ffmpeg -i /home/ubuntu/input.flv -s 640x480 -y -codec:a aac -b:a 44.1k -r 15 -b:v 1000k -codec:v h264 -f mp4 /home/ubuntu/output.mp4
ffmpeg version N-83323-g126e965 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
  configuration: --prefix=/home/ubuntu/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/ubuntu/ffmpeg_build/include --extra-ldflags=-L/home/ubuntu/ffmpeg_build/lib --bindir=/home/ubuntu/bin --enable-gpl --enable-libopus --enable-libvpx --enable-libvorbis --enable-libmp3lame --enable-libfdk-aac --enable-libx264 --enable-nonfree
  libavutil      55. 45.100 / 55. 45.100
  libavcodec     57. 75.100 / 57. 75.100
  libavformat    57. 66.101 / 57. 66.101
  libavdevice    57.  2.100 / 57.  2.100
  libavfilter     6. 72.100 /  6. 72.100
  libswscale      4.  3.101 /  4.  3.101
  libswresample   2.  4.100 /  2.  4.100
  libpostproc    54.  2.100 / 54.  2.100
/home/ubuntu/input.flv: Invalid data found when processing input

stderr:
ffmpeg version N-83323-g126e965 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
  configuration: --prefix=/home/ubuntu/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/ubuntu/ffmpeg_build/include --extra-ldflags=-L/home/ubuntu/ffmpeg_build/lib --bindir=/home/ubuntu/bin --enable-gpl --enable-libopus --enable-libvpx --enable-libvorbis --enable-libmp3lame --enable-libfdk-aac --enable-libx264 --enable-nonfree
  libavutil      55. 45.100 / 55. 45.100
  libavcodec     57. 75.100 / 57. 75.100
  libavformat    57. 66.101 / 57. 66.101
  libavdevice    57.  2.100 / 57.  2.100
  libavfilter     6. 72.100 /  6. 72.100
  libswscale      4.  3.101 /  4.  3.101
  libswresample   2.  4.100 /  2.  4.100
  libpostproc    54.  2.100 / 54.  2.100
/home/ubuntu/input.flv: Invalid data found when processing input

stdout:

But when I run

/home/ubuntu/bin/ffmpeg -i /home/ubuntu/input.flv -s 640x480 -y -codec:a aac -b:a 44.1k -r 15 -b:v 1000k -codec:v h264 -f mp4 /home/ubuntu/output.mp4

straight in the terminal, It works flawlessly. I think it has to do with how node runs the command but all my google searching has returned zero useful results. Any help is greatly appreciated.

Upvotes: 11

Views: 21930

Answers (2)

yaya
yaya

Reputation: 8243

Based on the other answer:

runCommand.js:

var spawn = require('child_process').spawn;
module.exports = (cmd, args, onData, onFinish) => {
    var proc = spawn(cmd, args.split(' '));
    proc.stdout.on('data', onData);
    proc.stderr.setEncoding("utf8")
    proc.stderr.on('data', err => console.log(err) );
    proc.on('close', onFinish);
}

main.js:

runCommand('ffmpeg', '-y -f concat -i list.txt -c copy output-final.mp4', 
        data => console.log(data), () => console.log('finished'))

Upvotes: 9

Bulent Vural
Bulent Vural

Reputation: 2688

This is not related to the async nature of node. Node process always waits for spawned child processes (created with both spawn and exec).

I suggest you to use spawn with ffmpeg due to number of reasons :

  • spawn handles the arguments in a different way than how exec does. It starts the process itself and passes the argument array to the process. exec however takes the whole command as a string and passes it to a shell process. This may lead to some escaping errors.

  • ffmpeg is most of the time a "long running" process. It is better to parse its output while it is still running. exec does not give the output until the process finishes.

  • ffmpeg could produce large amounts of output data. This can cause problems with exec as it starts the process with a limited buffer. (As Aikon has mentioned above). spawn passes the data as chunks in real time using streams.

Example with your cmd/args :

var spawn = require('child_process').spawn;

var cmd = '/home/ubuntu/bin/ffmpeg';

var args = [
    '-y', 
    '-i', '/home/ubuntu/input.flv',
    '-s', '640x480', 
    '-codec:a', 'aac', 
    '-b:a', '44.1k', 
    '-r', '15', 
    '-b:v', '1000k', 
    '-c:v','h264', 
    '-f', 'mp4', '/home/ubuntu/output.mp4'
];

var proc = spawn(cmd, args);

proc.stdout.on('data', function(data) {
    console.log(data);
});

proc.stderr.setEncoding("utf8")
proc.stderr.on('data', function(data) {
    console.log(data);
});

proc.on('close', function() {
    console.log('finished');
});

Upvotes: 33

Related Questions