# ffmpeg LGPL-only static build for SECRET MUSIC NORMALISER (macOS) Build date: 2026-09-02 Build host: macOS 26.6.1 (25G76), Apple clang 21.0.0 (clang-2100.1.1.101), Command Line Tools 26.6.0, SDK MacOSX 26.5, GNU make 3.81, python3 3.9.6. Deployment target: `-mmacosx-version-min=12.0` (both architectures, all libraries). No nasm/yasm (x86_64 built with `--disable-x86asm`), no pkg-config (tiny Python replacement generated by the build script into `tools/pkg-config`), no brew, no sudo. ## Result | File | Arch | Bytes | SHA-256 | |---|---|---|---| | `ffmpeg-aarch64-apple-darwin` | arm64 | 5 780 984 (5.5 MB) | `b63f62aae6f7127ad098b1e30db8141d963eaf324696e33aa65c4f5642d53dfb` | | `ffmpeg-x86_64-apple-darwin` | x86_64 | 5 949 056 (5.7 MB) | `a8cb194c1867f5f6b1481ac23b487779b7ab89808233226faad103b7738b805b` | | `ffmpeg-universal-apple-darwin` | x86_64 + arm64 (lipo) | 11 744 760 (11.2 MB) | `07899ddf2ef3c6c77e3b572844b9e77a7228318b4a5f2476870c8f0c2a287519` | Licence state (verified in `config.h` of both builds and in `ffmpeg -version` / `ffmpeg -L`): `CONFIG_GPL 0`, `CONFIG_NONFREE 0`, `CONFIG_VERSION3 0`, `CONFIG_NETWORK 0`. `ffmpeg -L` prints the GNU **Lesser** General Public License 2.1 text; no `--enable-gpl`, `--enable-nonfree` or `--enable-version3` in the configuration line. Dynamic dependencies (system only): `libSystem.B.dylib`, `AudioToolbox`, `CoreFoundation`, `CoreVideo`, `CoreMedia`. Everything else (lame, ogg, vorbis, opus, all ffmpeg libs) is linked statically. ## Sources (all kept in `../sources/` for the source-code offer) | Component | Version | Licence | Download URL | SHA-256 (verified) | |---|---|---|---|---| | FFmpeg | 9.0.1 | LGPL 2.1+ (this configuration) | https://ffmpeg.org/releases/ffmpeg-9.0.1.tar.xz | `cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635` | | LAME | 3.100 | LGPL 2+ | https://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz | `ddfe36cab873794038ae2c1210557ad34857a4b6bdc515785d1da9e175b1da1e` | | libogg | 1.3.6 | BSD-3 | https://downloads.xiph.org/releases/ogg/libogg-1.3.6.tar.xz | `5c8253428e181840cd20d41f3ca16557a9cc04bad4a3d04cce84808677fa1061` | | libvorbis | 1.3.7 | BSD-3 | https://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.tar.xz | `b33cc4934322bcbf6efcbacf49e3ca01aadbea4114ec9589d1b1e9d20f72954b` | | Opus | 1.6.1 | BSD-3 | https://downloads.xiph.org/releases/opus/opus-1.6.1.tar.gz | `6ffcb593207be92584df15b32466ed64bbec99109f007c82205f0194572411a1` | Checksum provenance: libogg/libvorbis/opus match the upstream `SHA256SUMS` files on downloads.xiph.org; LAME MD5 `83e260acbe4389b54fe08e0bdbf7cddb` matches the SourceForge file manifest; FFmpeg ships only a GPG signature (`ffmpeg-9.0.1.tar.xz.asc`, saved next to the tarball; gpg was not available on the build host, so the signature is stored but not verified). The build script re-checks every SHA-256 before extracting. Note: LAME 4.0 has since been released on SourceForge (Homebrew already ships it). 3.100 was used here as specified; switching is a version/checksum change in the script. ## Configure lines `$ROOT` = directory containing `build-ffmpeg-lgpl.sh`; `$P` = `$ROOT/prefix/`. For arm64: `--host=aarch64-apple-darwin`, `CC="clang -arch arm64"`; for x86_64: `--host=x86_64-apple-darwin`, `CC="clang -arch x86_64"`. Common: `CFLAGS="-O2 -mmacosx-version-min=12.0" LDFLAGS="-mmacosx-version-min=12.0"`. ``` lame: ./configure --host=$HOST --prefix=$P --disable-shared --enable-static --disable-frontend --disable-gtktest --disable-dependency-tracking CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" libogg: ./configure --host=$HOST --prefix=$P --disable-shared --enable-static --disable-dependency-tracking CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" libvorbis: sed -i '' 's/-force_cpusubtype_ALL//g' configure # obsolete flag rejected by the current Apple linker ./configure --host=$HOST --prefix=$P --disable-shared --enable-static --with-ogg=$P --disable-oggtest --disable-examples --disable-docs --disable-dependency-tracking CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" opus: ./configure --host=$HOST --prefix=$P --disable-shared --enable-static --disable-doc --disable-extra-programs --disable-dependency-tracking CC="$CC" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" ``` ffmpeg (arm64): ``` ./configure --prefix=$P --cc='clang -arch arm64' --pkg-config=$ROOT/tools/pkg-config --pkg-config-flags=--static --extra-cflags='-I$P/include -mmacosx-version-min=12.0' --extra-ldflags='-L$P/lib -mmacosx-version-min=12.0' --arch=arm64 --target-os=darwin --disable-everything --disable-network --disable-doc --disable-ffplay --disable-ffprobe --disable-autodetect --disable-debug --disable-gpl --disable-nonfree --disable-version3 --enable-audiotoolbox --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-protocol=file,pipe --enable-filter=loudnorm,volume,asoftclip,aresample,aformat,anull,sine --enable-indev=lavfi --enable-demuxer=mp3,mov,flac,wav,aiff,ogg --enable-decoder=mp3,mp3float,aac,alac,flac,vorbis,opus,libopus,libvorbis,speex,pcm_s16le,pcm_s24le,pcm_s32le,pcm_s16be,pcm_s24be,pcm_s32be,pcm_f32le,pcm_f32be,pcm_s8,pcm_u8 --enable-encoder=libmp3lame,aac,aac_at,alac,flac,libopus,libvorbis,pcm_s16le,pcm_s24le,pcm_s32le,pcm_s16be,pcm_s24be,pcm_s32be --enable-muxer=mp3,ipod,mp4,flac,wav,aiff,ogg,opus,null --enable-parser=mpegaudio,aac,flac,vorbis,opus --enable-bsf=aac_adtstoasc ``` ffmpeg (x86_64, cross-compiled on the arm64 host): identical, except `--cc='clang -arch x86_64'` and `--arch=arm64 --target-os=darwin` replaced by `--enable-cross-compile --arch=x86_64 --target-os=darwin --disable-x86asm`. Universal: `lipo -create ffmpeg-aarch64-apple-darwin ffmpeg-x86_64-apple-darwin -output ffmpeg-universal-apple-darwin` ## What is inside - Encoders: aac, aac_at, alac, flac, libmp3lame, libopus, libvorbis, pcm_s16le/s24le/s32le, pcm_s16be/s24be/s32be - Decoders: aac, alac, flac, mp3, mp3float, opus, libopus, vorbis, libvorbis, speex, pcm_s16/24/32 le+be, pcm_f32le/be, pcm_s8, pcm_u8 - Demuxers: mp3, mov/mp4/m4a, flac, wav, aiff, ogg — Muxers: mp3, ipod, mp4, flac, wav, aiff, ogg, opus, null - Filters: loudnorm, volume, asoftclip, aresample, aformat, anull, sine (test signal) — lavfi input device - Protocols: file, pipe — no network, no video codecs, no VideoToolbox, no zlib/iconv ## Smoke test (`../smoke-test.sh`, logs in `../tests/`) Inputs (generated with the app's previous GPL binary, 3 s 440 Hz stereo sine): mp3, m4a (AAC), m4a (ALAC 16/24), flac 16/24, wav 16/24/32/f32, aiff 16/24/32, ogg (Vorbis), ogg (Opus), opus. Per input: (1) loudnorm measurement, (2) encode with the exact codec arguments from `src/main.rs` to all 15 app targets (mp3 320k, aac_at 320k, aac 320k, alac s16p/s32p, flac s16/s32, pcm_s16le/s24le/s32le, pcm_s16be/s24be/s32be, libopus 256k, libvorbis q10) through `volume=…dB,asoftclip=type=hard,volume=-0.5dB`, (3) re-measure every output, (4) `-encoders` contains ` aac_at ` exactly once, (5) `-version`/`-L` licence check, (6) `lipo -info`, (7) size. | Binary | Run as | Result | |---|---|---| | ffmpeg-universal-apple-darwin | native arm64 | GREEN, 261/261 | | ffmpeg-universal-apple-darwin | `arch -x86_64` (Rosetta) | GREEN, 261/261 | | ffmpeg-x86_64-apple-darwin | `arch -x86_64` (Rosetta) | GREEN, 261/261 | | ffmpeg-aarch64-apple-darwin | native arm64 | GREEN, 261/261 | Additional check with embedded cover art (mp3/flac/m4a with JPEG and PNG pictures, both archs): measurement and encoding succeed with exit 0. ffmpeg prints a harmless warning `Could not find codec parameters for stream 1 (Video: mjpeg/png ...)` because no image decoders are built in; the app only evaluates the exit status and the `"input_i"` value, and passes `-vn`, so this has no effect. Not covered: Speex decoding (decoder is built in, but no Speex encoder was available to create a test file). ## Reproduce ``` ./build-ffmpeg-lgpl.sh # downloads (SHA-256 checked), builds both archs, lipo CLEAN=1 ./build-ffmpeg-lgpl.sh # same, but wipes build/ and prefix/ first ./smoke-test.sh out/ffmpeg-universal-apple-darwin ./smoke-test.sh out/ffmpeg-universal-apple-darwin "arch -x86_64" ``` ## Files in this directory - `build-ffmpeg-lgpl.sh` — copy of the build script (working copy lives one level up next to `sources/`; when running this copy set `ROOT=`) - `smoke-test.sh` — copy of the smoke test