3

I am facing an issue wanting to kill a FFmpeg process triggered by spawn from the child_process native NodeJs package.

Here is the script i use to trigger the ffmpeg process.

Assume that the conversion takes a long time, like about 2 hours.

/**
 * Execute a command line cmd
 * with the arguments in options given as an array of string
 * processStore is an array that will store the process during its execution
 * and remove it at the end of the command or when error occurs
 */
function execCommandLine({
   cmd,
   options = [],
   processStore = [],
}) {
  return new Promise((resolve, reject) => {
    const spwaned_process = childProcess.spawn(cmd, options);

    // Append the process to a buffer to keep track on it
    processStore.push(spwaned_process);

    // Do nothing about stdout
    spwaned_process.stdout.on('data', () => true);

    // Do nothing about stderr
    spwaned_process.stderr.on('data', () => true);

    spwaned_process.on('close', () => {
      const index = processStore.indexOf(spwaned_process);

      if (index !== -1) {
        processStore.splice(index, 1);
      }

      resolve();
    });

    spwaned_process.on('error', () => {
      const index = processStore.indexOf(spwaned_process);

      if (index !== -1) {
        processStore.splice(index, 1);
      }

      reject();
    });
  });
}

const processStore = [];

await execCommandLine({
  cmd: 'ffmpeg',

  options: [
    '-i',
    '/path/to/input',
    '-c:v',
    'libvpx-vp9',
    '-strict',
    '-2',
    '-crf',
    '30',
    '-b:v',
    '0',
    '-vf',
    'scale=1920:1080',
    '/path/to/output',
  ],

  processStore,
});

During the conversion, the following code is called to kill all process into the processStore, including the FFmpeg process that is triggered.

// getProcessStore() returns the const processStore array of the above script
getProcessStore().forEach(x => x.kill());

process.exit();

After the program exit, when i run ps -ef | grep ffmpeg, there is still some FFmpeg process running.

root 198 1 0 09:26 ? 00:00:00 ffmpeg -i /path/to/input -ss 00:01:47 -vframes 1 /path/to/output

root 217 1 0 09:26 ? 00:00:00 ps -ef

Do you have an idea about the way to kill a ffmpeg process properly ?

Community
  • 1
  • 1
user7364588
  • 1,014
  • 2
  • 12
  • 32

2 Answers2

4

As stated in the node.js documentation of subprocess.kill([signal]), the default sent signal is SIGTERM.

Ffmpeg do not terminature receiving SIGTERM as explained by @sashoalm in here.

Newer versions of ffmpeg don't use 'q' anymore, at least on Ubuntu Oneiric, instead they say to press Ctrl+C to stop them. So with a newer version you can simply use 'killall -INT' to send them SIGINT instead of SIGTERM, and they should exit cleanly.


So call x.kill('SIGINT');

Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
  • Note that this does not work on Windows because [Windows doesn't support signals](https://nodejs.org/api/process.html#process_signal_events) – Mikael Finstad Jul 10 '23 at 22:32
0

Aside from @Orelsanpls's answer there might another reason.

The processes that are remaining are not spawned directly from your main NodeJS process. In other words they are the childs of your spawned process.

Currently there is no method in child_process to kill the complete process tree but there is a feature request for it here.

Another solution is to use a module tree-kill. Here's an example I sneaked from their Github page:

Kill all the descendent processes of the process with pid 1, including the process with pid 1 itself:

var kill = require('tree-kill');
kill(1);

So what you might want to do is:

var treekill = require('tree-kill');
getProcessStore().forEach(x => treekill (x.pid));
Omid N
  • 947
  • 2
  • 11
  • 24