From 2cd7cd3eab854583a8ad83bbbc3c37ec5aa0e64c Mon Sep 17 00:00:00 2001 From: devilreef Date: Thu, 30 Apr 2026 19:28:10 +0600 Subject: [PATCH] fix(streamer): handle stdin EPIPE on ffmpeg exit, raise queue size, color_range tv --- streamer/src/ffmpeg.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/streamer/src/ffmpeg.ts b/streamer/src/ffmpeg.ts index 558a957..2dfc76a 100644 --- a/streamer/src/ffmpeg.ts +++ b/streamer/src/ffmpeg.ts @@ -19,14 +19,17 @@ export class Ffmpeg extends EventEmitter { start(): { videoIn: Writable; audioIn: Writable } { const args = [ "-loglevel", "warning", - // video in (mjpeg pipe on fd 3) + // video in (mjpeg pipe on fd 3) — yuvj420p source, large queue for stable pacing "-f", "image2pipe", "-c:v", "mjpeg", + "-thread_queue_size", "1024", "-r", String(this.opts.framerate), "-i", "pipe:3", // audio in (s16le pcm pipe on fd 4) - "-f", "s16le", "-ar", "48000", "-ac", "2", "-i", "pipe:4", + "-f", "s16le", "-ar", "48000", "-ac", "2", + "-thread_queue_size", "1024", + "-i", "pipe:4", // video encode "-c:v", "libx264", "-preset", "veryfast", - "-pix_fmt", "yuv420p", + "-pix_fmt", "yuv420p", "-color_range", "tv", "-b:v", this.opts.videoBitrate, "-maxrate", this.opts.videoBitrate, "-bufsize", "9000k", "-g", String(this.opts.framerate * 2), "-keyint_min", String(this.opts.framerate * 2), @@ -48,6 +51,12 @@ export class Ffmpeg extends EventEmitter { this.proc.stderr.on("data", (d) => this.emit("log", d.toString())); this.proc.on("exit", (code) => this.emit("exit", code)); + // ffmpeg exiting (e.g. RTMP drop) closes its stdins — subsequent writes + // emit EPIPE on these sockets, which would crash the supervisor as + // unhandled. Catch them; the proc.on("exit") handler does the actual restart. + videoIn.on("error", (err) => this.emit("log", `videoIn: ${err.message}`)); + audioIn.on("error", (err) => this.emit("log", `audioIn: ${err.message}`)); + return { videoIn, audioIn }; }