nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.46k stars 278 forks source link

child_process.spawn() not behaving properly with ffmpeg command #2731

Closed jeffstjean closed 4 years ago

jeffstjean commented 4 years ago

What steps will reproduce the bug?

I think I have isolated this to being a node issue but could be a lack of understanding of ffmpeg or child processes. On MacOS, I am using ffmpeg to on-the-fly encode a webcam into an hls format. I created a bash file that simply executes the command with the required options. When I execute it through Terminal, everything works as expected and I get a continuous stream of ts files. However, when I execute the bash file through a spawned child process. I continually get SIGABRT / Abort Trap 6 error.

server.js:

const { spawn } = require('child_process');

const record = spawn('./record');

record.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

record.stderr.on('data', (data) => {
    console.error(`stderr: ${data}`);
});

record.on('close', (code, signal) => {
  if(code) console.log(`child process exited with code ${code}`);
  else if(signal) console.log(`child process exited with signal ${signal}`);
});

record:

#!/bin/bash
ffmpeg -f avfoundation -pix_fmt uyvy422 -loglevel trace -y \
-framerate 30 -i "0" -c:v libx264 -crf 21 -preset veryfast \
-f hls -hls_time 4 -hls_playlist_type event public/stream/test.m3u8

I have also tried executing this without the use of a bash file and it has the same result.

How often does it reproduce? Is there a required condition?

100% of the time. It does not occur when the input is a file and not a streamable device (camera, etc.).

What is the expected behaviour?

NodeJS maintains an open child_process with the ffmpeg command that will continue until process termination:

ffmpeg version 4.2.3 Copyright (c) 2000-2020 the FFmpeg developers
  built with Apple clang version 11.0.3 (clang-1103.0.32.59)
  configuration: ...
Input #0, avfoundation, from '0':
  Duration: N/A, start: 620316.157633, bitrate: N/A
    Stream #0:0: Video: rawvideo (UYVY / 0x59565955), uyvy422, 320x240, 29.97 tbr, 1000k tbn, 1000k tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
---
Output #0, hls, to 'public/stream/test.m3u8':
...
frame=   38 fps=0.0 q=27.0 size=N/A time=00:00:00.46 bitrate=N/A speed=0.884x
frame=   53 fps= 51 q=27.0 size=N/A time=00:00:00.96 bitrate=N/A speed=0.939x
...
[hls @ 0x7f836a025c00] Opening 'public/stream/test.m3u8.tmp' for writing video:73kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
[libx264 @ 0x7f836a03ce00] frame I:1     Avg QP:23.45  size:  8643
[libx264 @ 0x7f836a03ce00] frame P:40    Avg QP:22.74  size:  1281
[libx264 @ 0x7f836a03ce00] frame B:117   Avg QP:22.69  size:   120
[libx264 @ 0x7f836a03ce00] consecutive B-frames:  0.6%  1.3%  1.9% 96.2%
[libx264 @ 0x7f836a03ce00] mb I  I16..4: 12.7% 36.3% 51.0%
[libx264 @ 0x7f836a03ce00] mb P  I16..4:  3.1%  1.9%  0.1%  P16..4: 49.8% 13.1%  6.6%  0.0%  0.0%    skip:25.4%
[libx264 @ 0x7f836a03ce00] mb B  I16..4:  0.2%  0.1%  0.0%  B16..8:  3.7%  0.4%  0.0%  direct:12.0%  skip:83.5%  L0:38.5% L1:50.1% BI:11.3%
[libx264 @ 0x7f836a03ce00] 8x8 transform intra:37.6% inter:37.4%
[libx264 @ 0x7f836a03ce00] coded y,uvDC,uvAC intra: 35.1% 85.0% 42.5% inter: 5.0% 21.1% 0.8%
[libx264 @ 0x7f836a03ce00] i16 v,h,dc,p:  7% 48%  4% 40%
[libx264 @ 0x7f836a03ce00] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu:  6% 32% 37%  5%  4%  3%  8%  2%  4%
[libx264 @ 0x7f836a03ce00] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 17% 20% 11%  8%  7%  6% 10%  8% 13%
[libx264 @ 0x7f836a03ce00] i8c dc,h,v,p: 61% 15% 21%  3%
[libx264 @ 0x7f836a03ce00] Weighted P-Frames: Y:20.0% UV:5.0%
[libx264 @ 0x7f836a03ce00] kb/s:112.15
Exiting normally, received signal 2.

What do you see instead?

...
stderr: [avfoundation @ 0x7fe5da814600] 'FaceTime HD Camera' opened

stderr: ./record: line 4: 73348 Abort trap: 6           ffmpeg -f avfoundation -pix_fmt uyvy422 -y -loglevel trace -framerate 30 -i "0" -c:v libx264 -crf 21 -preset veryfast -f hls -hls_time 4 -hls_playlist_type event public/stream/test.m3u8

child process exited with code 134
jeffstjean commented 4 years ago

Appears this issue only occurs when used the integrated terminal in VS Code. Really can't do much more debugging beyond that but maybe it's a VS issue and not Node. Thoughts?

bnoordhuis commented 4 years ago

It's ffmpeg that's aborting, not node. An abort trap is usually a tripped assert so my guess is that ffmpeg doesn't like something about the environment it's executed in.

You can try turning on core dumps with ulimit -c unlimited, then checking the core dump afterwards with lldb. Its bt command prints the stack trace leading up to the abort.

I'm moving this to nodejs/help but I can move it back if it turns out it's a Node.js issue after all.

jeffstjean commented 4 years ago

Just did a bit more testing to try and isolate the issue. I was originally running the script through the integrated command line in VS Code and turns out that was the variable that was causing the issue. Opening a Terminal process is a workaround.

Closing this issue as it is not node related. Hopefully this helps someone if they ever come across it.

abdelhbe commented 1 year ago

Hello, I have the same problem I think with node js spawn and ffmpeg. I have an .sh file that when run in a bash terminal works fine, but when run by chil_process.spawn will give me an error. (i'm not using any built in bash in a code editor)

What steps will reproduce the bug?

index.js

const { promisify } = require('util');
const child_process = require('child_process');

const ffmpegProcess = spawn("./toto.sh");

toto.sh

#!/bin/bash

ffmpeg -report -i /pathtovideo/video.mp4 -i /pathtoaudio/video.mp3 -y -acodec aac -filter:a atempo=1.35 -map 0:v -map 1:a -vf "subtitles=/pathtosubtitles.srt:force_style='Alignment=10,FontName=/pathToFont.ttf,Fontsize=14'" -t 4 /pathtooutput.mp4

Error

[Parsed_subtitles_0 @ 0x77c3180] libass API version: 0x1502002
[Parsed_subtitles_0 @ 0x77c3180] libass source: commit: 0.15.2-71-gcbeea94fc70a6322ecce4c4ff30bef2a9028c18a
[Parsed_subtitles_0 @ 0x77c3180] Shaper: FriBidi 1.0.11 (SIMPLE) HarfBuzz-ng 3.1.1 (COMPLEX)
[Parsed_subtitles_0 @ 0x77c3180] Using font provider fontconfig
[Parsed_subtitles_0 @ 0x77c3180] fontselect: (/pathtofont.ttf, 400, 0) -> /usr/share/fonts/urw-base35/NimbusSans-Regular.otf, 0, NimbusSans-Regular
[libx264 @ 0x67bd900] using SAR=1/1
[libx264 @ 0x67bd900] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!
Child process exited with code 1