# Building the FormatPlease core

The custom build is based on ffmpeg.wasm release v12.15, core 0.12.10,
FFmpeg 5.1.4 and Emscripten 3.1.40. Its production recipe is
`scripts/video/build-core.py`. The original `Dockerfile.upstream` is retained
for comparison; it is not the production build command.

The custom recipe omits the x265 source/build stage, `--enable-libx265`, and
`-lx265`. It keeps x264 and `--enable-gpl`, all other pinned codec versions,
the single-thread SIMD configuration, and FFmpeg's native HEVC decoder.
Upstream bindings and fftools are used without local C/C++ changes. A bounded
make job count and isolated native build directories replace Docker stages.
FreeType optional host PNG, bzip2 and Brotli detection is disabled, and its
internal zlib is used, to avoid accidentally linking native libraries installed
on the build host.

## Prerequisites

Linux with Python 3.10+ (including tarfile extraction filters), GCC/G++, make,
CMake, pkg-config, autoconf, autoconf-archive, automake, libtool and ragel. Install the official
Emscripten SDK at version 3.1.40:

```sh
git clone --depth 1 --branch 3.1.40 https://github.com/emscripten-core/emsdk.git /path/to/emsdk
cd /path/to/emsdk
./emsdk install 3.1.40
./emsdk activate 3.1.40
```

Source refs and download hashes are pinned in `sources.json`. The builder
verifies all archives before use. It does not resolve floating source branches.
The SDK's SDL port uses release 2.24.2 and validates its upstream ZIP hash.
Native build-tool versions may affect output bytes; bit-for-bit reproducibility
across arbitrary host systems is not promised.

## Compile

From the FormatPlease repository root:

```sh
python3 scripts/video/build-core.py \
  --work-dir /path/to/formatplease-core-build \
  --emsdk /path/to/emsdk --jobs 4
```

An executable tmpfs work directory can be used when disk space is limited.
`--resume` reuses completed stages in that work directory; use a fresh directory
for release verification or after changing build scripts. Stage logs are in
`logs/`, static archives in `install/`, and output JS/WASM/link map in `output/`.
The builder does not automatically promote its output to production.

## Rebuild from the website source downloads

Create a workspace containing `scripts/video/build-core.py` and
`third_party/ffmpeg-build/sources.json`, downloaded from the source index. The
script will retrieve and checksum the pinned archives itself. Alternatively,
put the downloaded, reconstructed archives in
`third_party/ffmpeg-build/downloads/` using the filenames in the manifest. The
same compile command works without the rest of the frontend project.

The original FFmpeg and ffmpeg.wasm archives retain optional upstream recipes
and license descriptions for components the custom production build does not
use. These are upstream build-system support, not a list of bundled libraries.
The standalone x265 source archive is not part of the custom core source set.

## Verification and promotion

Execute the candidate WASM with the official wrapper, capture `-version`,
`-buildconf`, `-encoders`, `-decoders`, `-demuxers` and `-muxers`, and run
`scripts/video/assert-core.mjs` on the captured JSON and linker map. The guard
requires all supported encoders and the internal HEVC decoder, and rejects
libx265 configuration or any HEVC encoder. Test HEVC and VP9 inputs to H.264
alongside the complete existing conversion matrix.

Only after successful validation, retain the JS/WASM, build record, hashes and
capability dump in `third_party/ffmpeg-build/`, and use a new asset version in
`binary.json`. The browser and preparation script share that version record.
Normal website builds validate the retained binaries, clear generated old video
assets, and publish only the approved custom core. No SDK is required for a
normal website build.
