178 lines
7.7 KiB
Markdown
178 lines
7.7 KiB
Markdown
# FFmpeg WebAssembly build record
|
|
|
|
av-tools ships the locally rebuilt, reviewed core profile
|
|
`0.12.10-reviewed-stack5m.1` in single-thread and multithread forms. The
|
|
browser wrapper is `@ffmpeg/ffmpeg` **0.12.15** and helpers are
|
|
`@ffmpeg/util` **0.12.2**. All versions and build inputs are exact, not ranges.
|
|
|
|
## Underlying build
|
|
|
|
The base ffmpeg.wasm upstream release is `v12.15` at
|
|
`71aa99d37c02a7b4c435275ca9ef50e612f6efa1`. Its Dockerfile selects:
|
|
|
|
- FFmpeg **n5.1.4** (libavcodec 59.37.100);
|
|
- Emscripten SDK **3.1.40**;
|
|
- production `-O3 -msimd128`;
|
|
- pthread flags for the MT build and explicit thread disabling for ST.
|
|
|
|
The reviewed profile then applies upstream ffmpeg.wasm commit
|
|
`b409e36475bc21f0451b5b1e1d126fa82871439a` to select a 5 MiB Emscripten stack.
|
|
That upstream fix addresses the libopus zero-byte/out-of-bounds failures
|
|
reported in issues `#591` and `#775`. The local driver additionally makes the
|
|
upstream container-stage dependency isolation explicit, disables native x265
|
|
assembly for the wasm32 build, bounds parallel jobs and refuses output that
|
|
contains the maintainer's repository or SDK paths.
|
|
|
|
The build configuration embedded in both copied WASM files is:
|
|
|
|
```text
|
|
--target-os=none
|
|
--arch=x86_32
|
|
--enable-cross-compile
|
|
--disable-asm
|
|
--disable-stripping
|
|
--disable-programs
|
|
--disable-doc
|
|
--disable-debug
|
|
--disable-runtime-cpudetect
|
|
--disable-autodetect
|
|
--nm=emnm
|
|
--ar=emar
|
|
--ranlib=emranlib
|
|
--cc=emcc
|
|
--cxx=em++
|
|
--objcc=emcc
|
|
--dep-cc=emcc
|
|
--extra-cflags='-I../../../../install/include -O3 -msimd128'
|
|
--extra-cxxflags='-I../../../../install/include -O3 -msimd128'
|
|
--enable-gpl
|
|
--enable-libx264
|
|
--enable-libx265
|
|
--enable-libvpx
|
|
--enable-libmp3lame
|
|
--enable-libtheora
|
|
--enable-libvorbis
|
|
--enable-libopus
|
|
--enable-zlib
|
|
--enable-libwebp
|
|
--enable-libfreetype
|
|
--enable-libfribidi
|
|
--enable-libass
|
|
--enable-libzimg
|
|
```
|
|
|
|
The ST string also has `--disable-pthreads --disable-w32threads
|
|
--disable-os2threads`; the MT build supplies Emscripten pthread flags instead.
|
|
At runtime the application executes `-version`, `-buildconf`, `-formats`,
|
|
`-codecs`, `-encoders` and `-filters` sequentially. Presets are enabled only
|
|
when the active core reports every required muxer, encoder and filter. Build
|
|
flags alone are not treated as a capability guarantee.
|
|
|
|
## External libraries
|
|
|
|
The upstream build references x264 `4-cores`, x265 3.4, libvpx v1.13.1, LAME
|
|
`master`, Ogg v1.3.4, Theora v1.1.1, Opus v1.3.1, Vorbis v1.3.3, zlib v1.2.11,
|
|
libwebp v1.3.2, FreeType VER-2-10-4, FriBidi v1.0.9, HarfBuzz 5.2.0, libass
|
|
0.15.0 and zimg release-3.0.5. These resolve to x264
|
|
`33cac6b77d5b9259c552156013a817ab23119612`, x265
|
|
`2bb5520e9596f361bf0ed81b3b8da0d7fd999069` and LAME
|
|
`2badea1974ae36cb8312afe99cff1e6b3b5decee`. All three commits predate the
|
|
ffmpeg.wasm v12.15 release; the branch-based x264/LAME commits remain the
|
|
respective branch tips. `SOURCE.md` records retrieval commands.
|
|
|
|
## Shipped files
|
|
|
|
| Mode | File | Bytes | SHA-256 |
|
|
| ---- | -------------------------- | -------: | ------------------------------------------------------------------ |
|
|
| ST | `st/ffmpeg-core.js` | 111804 | `80c05d79d0e4e9434977b76cb851d10ddf2bfd378570178700d2c43b8afdcb24` |
|
|
| ST | `st/ffmpeg-core.wasm` | 32232580 | `fe41ddc77220cef6c04f5d48eeffcaaaef179ad270642e098f9945013aa0c9dc` |
|
|
| MT | `mt/ffmpeg-core.js` | 128953 | `4f2650099ab70cb2583951c0421147c62bea6c18dfbba5cfae4d7698b5d0ab62` |
|
|
| MT | `mt/ffmpeg-core.wasm` | 32718455 | `abbead010cb0448b26f01a36a3c8c03a6b04aca07812ddd4719a7f4b6bf4b645` |
|
|
| MT | `mt/ffmpeg-core.worker.js` | 2115 | `f77898d631dc010b45c29c23cb4379c611a7d7b131bf591d08a656bb729a4ca3` |
|
|
|
|
The deterministic five-file repository artifact is 21,338,974 bytes with
|
|
SHA-256
|
|
`ebc068c6d096de55ae3335b04b7121130665f5b0ffa7a828067122733f55185f`.
|
|
|
|
`npm run vendor:ffmpeg` verifies and unpacks the deterministic tracked core
|
|
artifact to
|
|
`public/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/`;
|
|
`npm run vendor:verify-runtime` checks the build profile,
|
|
source/toolchain/patch identity, tracked artifact, generated paths, sizes and
|
|
digests without requiring a release-directory download. The stricter
|
|
`npm run vendor:verify` release gate also hashes the build-qualified
|
|
Corresponding Source archive. Vite then copies the verified bytes into `dist`.
|
|
A normal production build performs no network download and cannot fall back
|
|
to the older published npm core bytes.
|
|
|
|
## Multithread Chromium guardrail
|
|
|
|
The pinned multithread core can stall in Chromium when FFmpeg lets codecs use
|
|
the browser's full reported logical-core count. This is tracked upstream in
|
|
[ffmpeg.wasm issue 654](https://github.com/ffmpegwasm/ffmpeg.wasm/issues/654).
|
|
av-tools keeps the pthread core but adds `-threads 2` as an input and output
|
|
codec option for MT jobs. ST arguments remain unchanged. A regular browser
|
|
test performs an actual MT H.264/AAC conversion; loading the core alone is not
|
|
accepted as functional evidence.
|
|
|
|
Every execution also has a watchdog: an explicit shorter plan timeout wins;
|
|
otherwise the timeout is at least two minutes, scales to thirty times the
|
|
expected media duration, and is capped at the displayed four-hour product
|
|
limit. Timeout is still a failure, not a successful partial export.
|
|
|
|
## Long-session heap guardrail
|
|
|
|
The pinned Emscripten core was observed to end a later heterogeneous browser
|
|
workflow with a bare `Aborted()` even though the same command passed in a
|
|
fresh core and all per-job virtual files had been removed. Its `tile` filter
|
|
also aborted deterministically on a fourth consecutive contact sheet in local
|
|
stress runs. av-tools therefore refreshes an idle core before its seventeenth
|
|
media execution and before a fourth contact-sheet execution. Application queue
|
|
state, sources and completed results remain outside the worker and are not
|
|
discarded. A bare core abort also triggers recreation after cleanup so a
|
|
manual or queued retry starts on a fresh instance.
|
|
|
|
This is a conservative browser-memory guardrail, not a guarantee that sixteen
|
|
large jobs or three large contact sheets fit in memory. Cancellation and
|
|
failed filesystem-cleanup recovery continue to recreate the core immediately.
|
|
|
|
## Opus regression evidence
|
|
|
|
Published core 0.12.10 predates the upstream stack-size fix and stalled in the
|
|
real Opus preset path even though it advertised the `opus` muxer and
|
|
`libopus` encoder. Capability discovery alone was therefore not accepted as
|
|
enablement evidence.
|
|
|
|
On 2026-07-26 the Chromium harness used the checked
|
|
`tests/fixtures/generated/tone.wav` fixture (32,102 bytes, SHA-256
|
|
`0fd1f54d6be2f1cc7fd778775dd29cf184770d3716cf3394bf03ed54ac264c3c`)
|
|
and the real built-in `audio-opus` preset/command planner. After rebuilding
|
|
with the reviewed stack profile, the isolated ST and MT runs each:
|
|
|
|
- loaded the requested mode rather than a fallback;
|
|
- mapped PCM audio to `opus (libopus)`;
|
|
- opened the declared Opus output and reported its libopus encoder;
|
|
- returned non-empty bytes within its independent containment limit;
|
|
- re-probed the result as positive-duration Opus audio.
|
|
|
|
```sh
|
|
# Record JSON evidence.
|
|
npm run evidence:opus
|
|
|
|
# Positive Opus enablement/release gate.
|
|
npm run test:opus-regression
|
|
```
|
|
|
|
The Opus audio and VP9/Opus presets are enabled only when the reviewed-core
|
|
lock records both passing modes and runtime discovery finds every preset
|
|
requirement. This is exact Chromium fixture evidence, not a claim about every
|
|
browser, input or possible Opus build.
|
|
|
|
## Licence consequence
|
|
|
|
The actual core build enables GPL and links external codecs. The wrapper/util
|
|
are MIT. av-tools is GPL-3.0-or-later, and the distributed application must
|
|
not be described as MIT-only. Publish the reviewed Corresponding Source and
|
|
external notices with the binary release. See `LICENSE`, `LICENSES/`,
|
|
`THIRD_PARTY_NOTICES.md` and `SOURCE.md`.
|