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
- 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.
- 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.
- 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).
- Raise memory limits in Docker/Kubernetes so the FFmpeg pre-stitcher is not OOM-killed mid-render.
- 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
- Disable parallel encoding (disallowParallelEncoding: true / --disallow-parallel-encoding) in memory-constrained containers - it is auto-enabled only when free memory looks sufficient, which can be wrong.
- Keep Remotion's bundled FFmpeg/compositor binaries - avoid custom binariesDirectory overrides, and re-clear them after upgrades.
- Run a short smoke render in CI before long jobs to catch broken FFmpeg setups early.
- Use --log=verbose on failures; the FFmpeg stderr printed with sibling 'FFmpeg quit' errors usually names the real cause.
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
- The start time for inline audio asset ${asset.id} changed fr
- Failed to create WebGL texture
- Could not find ${library} DLL for ${arch}
- No audio stream found in '${input_path}'. Ensure the video c
- Frame evicted from cache
AI-assisted analysis of remotion-dev/remotion@8f97758157 (2026-08-22).
Data as JSON: /api/errors/139e09ee8e9e6638.
Report an issue: GitHub.