Files
av-tools/docs/PERFORMANCE.md

96 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.