remotion-dev/remotion · error · Error

FFmpeg stdin is not available while trying to pipe frame ${f

Error message

FFmpeg stdin is not available while trying to pipe frame ${frame} to it.

What it means

During renderMedia()/internalRenderMediaRaw, Remotion automatically uses parallel encoding when the machine has enough free memory and the codec supports it (render-media.ts:379): each rendered frame buffer is piped straight into an FFmpeg 'pre-stitcher' process via stdin. Right before writing, the code reads stitcherFfmpeg.stdin and throws when the FFmpeg process was never created or its stdin stream is already gone. The two checks just above throw 'FFmpeg already quit'/'FFmpeg quit with code' when the exit status is known - this message covers the remaining case where stdin is simply unavailable.

Source

Thrown at packages/renderer/src/render-media.ts:725

								}

								const id = startPerfMeasure('piping');
								const exitStatus = preStitcher?.getExitStatus();
								if (exitStatus?.type === 'quit-successfully') {
									throw new Error(
										`FFmpeg already quit while trying to pipe frame ${frame} to it. Stderr: ${exitStatus.stderr}`,
									);
								}

								if (exitStatus?.type === 'quit-with-error') {
									throw new Error(
										`FFmpeg quit with code ${exitStatus.exitCode}${exitStatus.signal ? ` (signal ${exitStatus.signal})` : ''} while piping frame ${frame}. Stderr: ${exitStatus.stderr}`,
									);
								}

								const stdin = stitcherFfmpeg?.stdin;
								if (!stdin) {
									throw new Error(
										`FFmpeg stdin is not available while trying to pipe frame ${frame} to it.`,
									);
								}

								await writeWithBackpressure({data: buffer, writable: stdin});
								stopPerfMeasure(id);

								const frameIndex = framesToRender.indexOf(frame);
								setFrameToStitch(
									framesToRender[frameIndex + 1] ?? lastFrameToRender + 1,
								);
							}
						: null,
					webpackBundleOrServeUrl: serveUrl,
					onBrowserLog,
					onDownload,
					timeoutInMilliseconds,
					chromiumOptions,

View on GitHub (pinned to 8f97758157)

Solutions

  1. Disable parallel encoding: pass disallowParallelEncoding: true to renderMedia() or use the CLI flag --disallow-parallel-encoding. Frames are then written to disk and stitched afterwards, avoiding the stdin pipe entirely.
  2. Re-run with verbose logging (--log=verbose or logLevel: 'verbose') and inspect the FFmpeg stderr printed just before the throw - an accompanying 'FFmpeg quit with code' message names the real cause.
  3. Verify the FFmpeg/compositor binary works in your environment: remove any binariesDirectory override so Remotion uses its own downloaded binary (npx remotion versions shows it).
  4. Raise memory limits in Docker/Kubernetes so the FFmpeg pre-stitcher is not OOM-killed mid-render.
  5. If it reproduces with a stock setup and matching versions, file a Remotion issue with the verbose log and composition details.

Example fix

// before
await renderMedia({
  composition,
  serveUrl,
  codec: 'h264',
  // parallel encoding auto-enabled (enough free memory), FFmpeg stdin dies mid-render
});

// after
await renderMedia({
  composition,
  serveUrl,
  codec: 'h264',
  disallowParallelEncoding: true, // stitch from disk; no FFmpeg stdin pipe
});
Defensive patterns

Strategy: fallback

Validate before calling

// Smoke test: verify a tiny parallel-encoded render works before long jobs
import {renderMedia, getCompositions} from '@remotion/renderer';

const canParallelEncode = async () => {
  try {
    await renderMedia({composition: smokeComp, serveUrl, codec: 'h264', output: '/tmp/smoke.mp4'});
    return true; // parallel encoding + FFmpeg piping works in this environment
  } catch {
    return false; // fall back to disallowParallelEncoding for real renders
  }
};

Try / catch

const ffmpegPipeFailure = /FFmpeg (stdin is not available|already quit|quit with code)/;

try {
  await renderMedia({composition, serveUrl, codec: 'h264'});
} catch (err) {
  if (ffmpegPipeFailure.test(err.message)) {
    // fall back: stitch from disk instead of piping frames into FFmpeg
    await renderMedia({composition, serveUrl, codec: 'h264', disallowParallelEncoding: true});
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Parallel encoding is active (auto-selected based on free memory) and FFmpeg terminates before or during frame piping: a missing/incompatible FFmpeg binary (custom binariesDirectory, broken download), encoder options the binary rejects for the chosen codec, the process being OOM-killed in constrained containers, or stdin closed after exit before the exit status was recorded.

Common situations: Docker/CI images with tight memory limits where FFmpeg is killed mid-render; an old FFmpeg build pinned via a custom binaries directory; long 4K/high-fps renders where memory estimates said parallel encoding was safe but the encoder later died; a Remotion upgrade that changed the pre-stitcher protocol while a cached older binary is used.

Related errors


AI-assisted analysis of remotion-dev/remotion@8f97758157 (2026-08-22). Data as JSON: /api/errors/139e09ee8e9e6638. Report an issue: GitHub.