ffmpegwasm / ffmpegwasm/ffmpeg.wasm

core-mt: RuntimeError: Aborted(OOM) decoding a single 4K (2160x3840) H.264 frame, even before any filter runs

Open
#946 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.