Files
LibreMediaConverter/tools/ffmpeg/Containerfile
T
JMR-devandClaude Opus 5 b082cea889 Add containerized FFmpeg build producing a 16 KB-aligned GPL AAR
There is no usable prebuilt FFmpeg for Android any more. arthenica/ffmpeg-kit
is archived and its binaries were deleted from Maven Central, so every
com.arthenica:ffmpeg-kit-* coordinate 404s and all of its release tags have
zero assets. Maven Central's search index still lists the old versions, which
misleads; the files behind those entries are gone. The successor,
ffmpeg-kit-next, is source-only by design. Building it ourselves is the only
remaining option, not a preference.

ffmpeg-kit-next is Nix-only -- there is no plain android.sh, only
nix-android.sh and a flake -- so the toolchain lives in a container rather
than on the developer's machine. The recipe doubles as the reproducibility
artifact F-Droid expects and as the GPL corresponding-source obligation.

Four problems this path hits, none of them documented upstream:

- The nixos/nix base image already ships bash, coreutils and git; installing
  them collides with the existing profile entries and fails the image build.
- Upstream scripts use #!/bin/bash but the image provides only /bin/sh, so
  start-android.sh dies with "cannot execute: required file not found" after
  the entire toolchain has been built.
- Gradle's AAPT2 comes from Maven as a prebuilt binary linked against FHS
  paths that do not exist under Nix, failing with "Daemon startup failed"
  after the whole native build succeeds. Nixpkgs' Android SDK ships an
  already-patched aapt2, so Gradle is pointed at that.
- A bare '*.aar' find also collects every AAR Gradle unpacked into its own
  caches, so the copy is scoped to the ffmpeg-kit outputs.

The NDK stays at r27d as the flake pins it. Do not "upgrade" to r28+:
android/jni/Android.mk applies -Wl,-z,max-page-size=16384 manually precisely
because r27 predates automatic alignment, and the result is verified 16 KB
compliant as-is.

Verified against the produced artifact: every .so on both ABIs reports LOAD
align 0x4000, libraries are separate rather than a static monolith as the
GPL relinking obligation requires, and the embedded configure line confirms
--enable-gpl --enable-version3 with x264, x265, SVT-AV1, LAME, libass and
the MediaCodec wrappers. Note that --enable-small and --enable-lto
internalize symbols, so absence from strings output proves nothing; check
the configure line instead.

The 35 MB AAR itself is gitignored. F-Droid strips checked-in prebuilt
native libraries, and the recipe is the artifact of record.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 21:19:01 -05:00

34 lines
1.5 KiB
Docker

# Reproducible FFmpeg build environment for ffmpeg-kit-next.
#
# ffmpeg-kit-next is Nix-only: the repository ships nix-android.sh and a flake, and
# there is no plain android.sh. Rather than install Nix on a developer machine, the
# whole toolchain lives in this image. It also serves as the reproducibility artifact
# F-Droid expects.
#
# The flake pins Android NDK 27.3.13750724 (r27d) itself and applies
# -Wl,-z,max-page-size=16384 for arm64-v8a and x86_64 in android/jni/Android.mk, so
# the output is 16 KB page-size compliant without needing NDK r28+ on the host.
#
# The base image already provides git, bash, curl and tar. Compilers and build tools
# (make, cmake, autotools, pkg-config) are supplied by the flake's devShell at build
# time, so nothing further is installed here — `nix profile install` would in fact
# collide with the base image's existing profile entries.
FROM docker.io/nixos/nix:2.35.2
# nix-android.sh points NIX_USER_CONF_FILES at the repo's own nix.conf, which enables
# the flakes and nix-command experimental features. Set them here too so that plain
# `nix` invocations behave the same way.
RUN mkdir -p /etc/nix && \
printf 'experimental-features = nix-command flakes\naccept-flake-config = true\nwarn-dirty = false\nmax-jobs = auto\n' \
>> /etc/nix/nix.conf
# Upstream's scripts/*.sh use `#!/bin/bash`, but this image provides only /bin/sh.
RUN ln -sf /bin/sh /bin/bash
WORKDIR /work
COPY build-ffmpeg.sh /usr/local/bin/build-ffmpeg.sh
RUN chmod +x /usr/local/bin/build-ffmpeg.sh
ENTRYPOINT ["/usr/local/bin/build-ffmpeg.sh"]