Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

running ffmpeg via nodejs error

Tags:

node.js

ffmpeg

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.

like image 682
Greyhammer Avatar asked Feb 02 '17 21:02

Greyhammer


2 Answers

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');
});
like image 55
Bulent Vural Avatar answered Oct 20 '22 10:10

Bulent Vural


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'))
like image 42
yaya Avatar answered Oct 20 '22 10:10

yaya