#!/bin/bash # Builds ffmpeg + ffprobe into /opt/hf-media and packs /out/hf-media-linux-.tar.gz. # Codec libraries link statically; glibc and the TLS stack stay dynamic (a static glibc build crashed on Lambda). set -euo pipefail PREFIX=/opt/hf-media DEPS=/build/deps SRC=/build/src JOBS=$(nproc) export PKG_CONFIG_PATH="$DEPS/lib/pkgconfig:$DEPS/lib64/pkgconfig" export CFLAGS="-O2 -fPIC" CXXFLAGS="-O2 -fPIC" mkdir -p "$SRC" "$DEPS" "$PREFIX/share/licenses" /out fetch() { local name=$1 sum url read -r sum url < <(awk -v n="$name" '$1 == n { print $2, $3 }' /build/sources.txt) curl -fsSL --retry 3 -o "$SRC/$name" "$url" echo "$sum $SRC/$name" | sha256sum -c --quiet tar -xf "$SRC/$name" -C "$SRC" } license() { mkdir -p "$PREFIX/share/licenses/$1" && cp "${@:2}" "$PREFIX/share/licenses/$1/"; } read -r x264_commit x264_url < <(awk '$1 == "x264" { print $2, $3 }' /build/sources.txt) git clone -q "$x264_url" "$SRC/x264" git -C "$SRC/x264" checkout -q "$x264_commit" [ "$(git -C "$SRC/x264" rev-parse HEAD)" = "$x264_commit" ] (cd "$SRC/x264" && ./configure --prefix="$DEPS" --enable-static --enable-pic --disable-cli && make -j"$JOBS" && make install) license x264 "$SRC/x264/COPYING" fetch x265_4.1.tar.gz # 8-bit x265 with the 10-bit library linked in (x265's multilib layout): HDR renders encode yuv420p10le. # SVE2 kernels need -march=armv9-a, which the base's gcc 11 does not know (x86 ignores the flag). x265=(-S "$SRC/x265_4.1/source" -DCMAKE_BUILD_TYPE=Release -DENABLE_SHARED=OFF -DENABLE_CLI=OFF -DENABLE_SVE2=OFF) cmake "${x265[@]}" -B "$SRC/x265-10" -DHIGH_BIT_DEPTH=ON -DEXPORT_C_API=OFF cmake --build "$SRC/x265-10" -j"$JOBS" cmake "${x265[@]}" -B "$SRC/x265-8" -DCMAKE_INSTALL_PREFIX="$DEPS" -DLINKED_10BIT=ON \ -DEXTRA_LIB="$SRC/x265-10/libx265.a" cmake --build "$SRC/x265-8" -j"$JOBS" cmake --install "$SRC/x265-8" printf 'CREATE %s\nADDLIB %s\nADDLIB %s\nSAVE\nEND\n' "$DEPS/lib/libx265.a" \ "$SRC/x265-8/libx265.a" "$SRC/x265-10/libx265.a" | ar -M license x265 "$SRC/x265_4.1/COPYING" fetch libvpx-1.15.0.tar.gz (cd "$SRC/libvpx-1.15.0" && ./configure --prefix="$DEPS" --enable-static --disable-shared --enable-pic \ --enable-vp9-highbitdepth --disable-examples --disable-tools --disable-docs --disable-unit-tests && make -j"$JOBS" && make install) license libvpx "$SRC/libvpx-1.15.0/LICENSE" "$SRC/libvpx-1.15.0/PATENTS" fetch opus-1.5.2.tar.gz (cd "$SRC/opus-1.5.2" && ./configure --prefix="$DEPS" --enable-static --disable-shared --with-pic \ --disable-doc --disable-extra-programs && make -j"$JOBS" && make install) license opus "$SRC/opus-1.5.2/COPYING" fetch zimg-3.0.5.tar.gz (cd "$SRC/zimg-release-3.0.5" && ./autogen.sh && ./configure --prefix="$DEPS" --enable-static --disable-shared \ --with-pic && make -j"$JOBS" && make install) license zimg "$SRC/zimg-release-3.0.5/COPYING" fetch dav1d-1.5.1.tar.xz meson setup "$SRC/dav1d-build" "$SRC/dav1d-1.5.1" --prefix="$DEPS" --libdir=lib --buildtype=release \ --default-library=static -Denable_tools=false -Denable_tests=false ninja -C "$SRC/dav1d-build" install license dav1d "$SRC/dav1d-1.5.1/COPYING" fetch ffmpeg-7.0.2.tar.xz # No --static pkg-config: gnutls.pc then names a libgmp.a from its own RPM build tree. The deps above # exist only as .a, so they link statically anyway; --extra-libs carries their private libraries. (cd "$SRC/ffmpeg-7.0.2" && ./configure --prefix="$PREFIX" \ --extra-cflags="-I$DEPS/include" --extra-ldflags="-L$DEPS/lib" --extra-libs="-lstdc++ -lpthread -lm -ldl" \ --enable-gpl --enable-version3 --disable-debug --disable-doc --disable-ffplay --disable-autodetect \ --enable-gnutls --enable-zlib --enable-libx264 --enable-libx265 --enable-libvpx --enable-libopus \ --enable-libzimg --enable-libdav1d && make -j"$JOBS" && make install) license ffmpeg "$SRC/ffmpeg-7.0.2/COPYING.GPLv3" "$SRC/ffmpeg-7.0.2/LICENSE.md" rm -rf "$PREFIX/include" "$PREFIX/lib" "$PREFIX/share/ffmpeg" strip "$PREFIX/bin/ffmpeg" "$PREFIX/bin/ffprobe" # Bundle every shared library the bare base image lacks (gnutls, nettle); the rpath finds them. mkdir -p "$PREFIX/lib" ldd "$PREFIX/bin/ffmpeg" "$PREFIX/bin/ffprobe" | awk '$2 == "=>" { print $3 }' | sort -u | while read -r lib; do if ! grep -qx "$(rpm -qf --qf '%{NAME}' "$lib")" /build/base-rpms.txt; then cp -L "$lib" "$PREFIX/lib/" && patchelf --set-rpath '$ORIGIN' "$PREFIX/lib/$(basename "$lib")" echo "$(rpm -qf "$lib") $(basename "$lib")" >>"$PREFIX/share/licenses/bundled-libraries.txt" fi done patchelf --set-rpath '$ORIGIN/../lib' "$PREFIX/bin/ffmpeg" "$PREFIX/bin/ffprobe" cp /build/sources.txt "$PREFIX/share/licenses/sources.txt" tar --sort=name --mtime="@$SOURCE_DATE_EPOCH" --owner=0 --group=0 --numeric-owner -C /opt -cf - hf-media | gzip -n -9 >"/out/hf-media-linux-$(uname -m).tar.gz"