# Performance and resource observations ffmpeg.wasm runs native media code compiled to WebAssembly. It is normally much slower than desktop FFmpeg and may hold source, decoded frames, filters and output at once. No hardware encoder is used. ## Fixed download footprint Uncompressed self-hosted core assets for `0.12.10-reviewed-stack5m.1`: | Mode | JavaScript/worker | WASM | Total | | ------------- | ------------------: | -----------: | -----------: | | single-thread | 111,804 B | 32,232,580 B | 32,344,384 B | | multithread | 128,953 B + 2,115 B | 32,718,455 B | 32,849,523 B | Only the selected mode is loaded. HTTP compression may reduce JavaScript transfer but not necessarily WASM to the same degree; report transfer and decoded sizes separately. Versioned core assets may be cached immutably. ## Benchmark record One opt-in pinned-core baseline was recorded on 2026-07-24 with Chrome for Testing 149.0.7827.55 (Playwright 1.61.1), Linux 7.0.0-28 on Ubuntu 24.04, Intel Core i7-8700 (6 cores/12 threads) and 31 GiB RAM. `navigator.hardwareConcurrency` reported 12 and every sample was cross-origin-isolated. Each row used a fresh browser context; the first core fetch may populate the browser HTTP cache, so later rows are explicitly potentially warm-cache observations. Preset: MP4, H.264/libx264 CRF 23 medium, AAC. Times are milliseconds. “Export end-to-end” spans the Convert click through result construction, cleanup, verification re-probe and visible result. The three narrower engine columns come from the export validation report. | Source | Input bytes | Mode | Init | Probe | FFmpeg exec | Output read | Cleanup | Export end-to-end | Output bytes | Observed JS heap | | --------------------------------------- | ----------: | ----------------- | ----: | ----: | ----------: | ----------: | ------: | ----------------: | -----------: | ---------------: | | 2 s, 160×90 H.264/AAC synthetic pattern | 34,057 | ST | 294.4 | 131.4 | 315.6 | 1.0 | 1.2 | 422.4 | 68,700 | 10,000,000 B | | same | 34,057 | MT (`-threads 2`) | 914.5 | 126.4 | 294.3 | 1.3 | 1.9 | 416.8 | 68,753 | 10,000,000 B | | 6 s, 640×360 H.264/AAC synthetic loop | 526,632 | ST | 270.2 | 163.6 | 6,854.1 | 1.3 | 0.8 | 7,030.9 | 585,981 | 15,200,000 B | | same | 526,632 | MT (`-threads 2`) | 946.3 | 121.6 | 4,053.1 | 1.6 | 0.5 | 4,497.5 | 585,884 | 11,200,000 B | Command: ```sh npm run benchmark:browser ``` Result: **1 passed (18.2 s)**; test body 17.6 s. Chromium exposed `performance.memory.usedJSHeapSize`, but this coarse post-operation value is not a peak-WASM-memory measurement. One run is not a statistical distribution; cold-cache repetitions, median/range, mobile and other-browser measurements remain release-quality evidence gaps. Never present this workstation as a universal promise. ## Measurement boundaries - initialization: wrapper construction through successful capability query; - probe: input mount/write through parsed ffprobe JSON; - conversion: accepted command through exit code; - output read: exit through Blob/result construction; - cleanup: final result read through job directory unmount/delete; - cancellation: cancel request through worker termination and recoverable idle state (fresh-engine load is a separate measure). Progress events are experimental estimates and not a timer. Use monotonic browser timing around lifecycle boundaries. ## Product limits Default soft input warning is 256 MiB; hard single/total input is 1.5 GiB. Estimated output warns at 512 MiB and is blocked at 1 GiB. FFmpeg jobs are serial; the application retains at most eight scheduled operations in its in-memory queue. Timeline clips are capped at 100, streams per input at 64, images at 8192×8192/67,108,864 pixels, generated output files at 255, contact-sheet cells at 500, scene-change results at 100, crossfades at 10 seconds and runtime at four hours. Scene selection is a bounded two-step workflow but its analysis step can still decode the complete source when few frames meet the threshold. The documented ffmpeg.wasm input ceiling is 2 GiB, but real limits can be substantially lower on mobile or memory-constrained browsers. Import does not start FFmpeg. Recognized local audio/video can begin browser playback from its temporary object URL while a native media element reads lightweight duration/dimensions. Detailed FFprobe inspection starts only when requested or required for an export and has a bounded, size-aware watchdog: 30 seconds for small files, a two-MiB-per-second budget for larger files, and a five-minute ceiling. A detailed-inspection timeout is nonfatal; browser playback and basic file information remain available. Completed probe metadata remains authoritative for stream mapping, remux safety, chapters, tags, subtitles/attachments and export validation. Lowering resolution, duration, frame rate, passes and output count reduces work. MT can be faster but consumes more memory/CPU and requires isolation; ST is not inherently a low-memory guarantee.