ffmpegwasm / ffmpegwasm/ffmpeg.wasm
core-mt: RuntimeError: Aborted(OOM) decoding a single 4K (2160x3840) H.264 frame, even before any filter runs
- Dominant language
- C
- Stars
- 17.8k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
## Environment
- `@ffmpeg/ffmpeg`: 0.12.15
- `@ffmpeg/core-mt`: 0.12.9
- Browser: Chromium (both headless and non-headless, via Playwright 1.63.0), macOS (arm64)
- Hosted with `Cross-Origin-Opener-Policy: same-origin` / `Cross-Origin-Embedder-Policy: require-corp` set (via Cloudflare Pages `_headers`), confirmed `self.crossOriginIsolated === true`
## Repro
Input: a 5.16s H.264 clip, 2160x3840 (portrait 4K), 25fps, ~20.7Mbps, ~13MB file.
```js
const ffmpeg = new FFmpeg();
await ffmpeg.load({
coreURL: await toBlobURL('/core-mt/ffmpeg-core.js', 'text/javascript'),
wasmURL: await toBlobURL('/core-mt/ffmpeg-core.wasm', 'application/wasm'),
workerURL: await toBlobURL('/core-mt/ffmpeg-core.worker.js', 'text/javascript'),
});
await ffmpeg.writeFile('input.mp4', await fetchFile('./test-clip.mp4'));
await ffmpeg.exec([
'-i', 'input.mp4',
'-vf', 'scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,setsar=1',
'-r', '30', '-an', '-c:v', 'libx264', '-pix_fmt', 'yuv420p',
'output.mp4',
]);
```
## Observed
In a real (non-headless) browser, this fails quickly with:
```
Uncaught RuntimeError: Aborted(OOM). Build with -sASSERTIONS for more info.
```
right after logging `frame=1 fps=0.0 ...` (i.e. it fails on/around decoding the very first frame, before the scale/crop filter would have reduced its size).
**In headless Chromium specifically** (`chromium.launch()` with default headless mode via Playwright), the same repro does not surface this error at all — instead it hangs indefinitely at `frame=1` with no further output and no thrown error, for as long as I waited (tested up to 3 minutes). Only switching to `headless: false` surfaced the actual `Aborted(OOM)`. That discrepancy seems worth knowing about independently of the OOM itself, since it means headless/CI-based testing of `core-mt` can silently hide this failure mode as a hang rather than an error.
## Expectation
A single 2160x3840 frame is ~25MB raw (yuv420p is smaller, but still substantial). I'd expect either:
- this resolution to be within the default heap budget for `core-mt`, or
- a clear, immediate memory-limit error rather than an OOM abort after starting to process, or a silent hang under headless Chromium.
The single-threaded `@ffmpeg/core` (0.12.10) does not OOM on the same input (it completes, just very slowly — a separate performance observation, not part of this report).
## Related
Possibly related to #183, though that report is from 2021 against the pre-0.12 API (`ffmpeg.run`), a different OS/browser, and a different command (watermark overlay on a 100MB file) — filing separately since it's a different version/repro shape and I have a clean, versioned, minimal repro for this one.
Happy to share the full repro project (static HTML/JS + Playwright driver script) if useful.
Contributor guide
Research direction
Start with the supplied FFmpeg load and exec reproduction using core-mt's ffmpeg-core.js, ffmpeg-core.wasm, and ffmpeg-core.worker.js. Run it in headless and non-headless Chromium through Playwright, then investigate the first-frame OOM versus hang behavior before the scale filter runs. Done means the failure is explained and the issue has a reproducible fix or a clear memory-limit error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, playwright, wasm
- Domain
- performance, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100