ListenBook Audiobooks (iOS) dynamically links the following libraries from the
FFmpeg project under the
GNU Lesser General Public License v2.1 or later:
libavformat, libavcodec, libavutil, libswresample.
This software uses code of FFmpeg licensed under the LGPLv2.1 and its source can be downloaded here.
3a0867c2bfda4a4d4309ca1a8cbdc6175e67f587 (tag n7.1.5)8d8312b058f5ca97ac80a96c480809b50bd51bc6678e6a639b1d6214d99a636achanges.diff applies). No --enable-gpl or
--enable-nonfree options are used.tag: n7.1.5 commit: 3a0867c2bfda4a4d4309ca1a8cbdc6175e67f587 min_ios: 26.0 demuxers: ogg,asf,matroska,mov,flac,wav,aiff,ape,tta,wv,dsf,dff,mp3,aac,caf,w64,rm,mpc,mpc8 decoders: vorbis,opus,flac,alac,wmav1,wmav2,wmapro,wmavoice,wmalossless,ape,tta,wavpack,mp3,mp3float,mp2,mp1,aac,aac_latm,pcm_s16le,pcm_s16be,pcm_s24le,pcm_u8,pcm_f32le,cook,sipr,ra_144,ra_288,musepack7,musepack8,dsd_lsbf,dsd_msbf,dsd_lsbf_planar,dsd_msbf_planar parsers: vorbis,opus,flac,aac,aac_latm,mpegaudio,cook flags: -fno-stack-check (FFmpeg asm vs clang stack probing on Apple targets)
This script reproduces the exact binaries shipped in the app (dylib → framework → xcframework, dynamic linking, iOS device arm64 + simulator arm64):
#!/bin/bash
# Reproducible FFmpeg build for ListenBook (audit W5-1/W5-2).
#
# - Source is pinned to an exact tag AND commit SHA (verified after checkout).
# - Paths are relative to this script — no hardcoded user directories.
# - The configure line is recorded next to the outputs.
# - Only LGPL components are enabled (no --enable-gpl / --enable-nonfree);
# audio demuxers/decoders/parsers only, dynamic linking.
# - `-fno-stack-check`: clang's stack-probing is incompatible with FFmpeg's
# hand-written assembly stack usage on Apple targets (link-time/runtime
# crashes); every known iOS FFmpeg recipe disables it. Documented, kept.
#
# Usage: ./build.sh # clone+verify, build device+sim, package, install
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$ROOT/.." && pwd)"
cd "$ROOT"
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
TAG="n7.1.5"
# Commit the tag must resolve to (git ls-remote, recorded 2026-07-20) — a
# moved/replaced tag fails the build instead of silently building other code.
PINNED_COMMIT="3a0867c2bfda4a4d4309ca1a8cbdc6175e67f587"
MIN_IOS="26.0"
DEMUXERS="ogg,asf,matroska,mov,flac,wav,aiff,ape,tta,wv,dsf,dff,mp3,aac,caf,w64,rm,mpc,mpc8"
DECODERS="vorbis,opus,flac,alac,wmav1,wmav2,wmapro,wmavoice,wmalossless,ape,tta,wavpack,mp3,mp3float,mp2,mp1,aac,aac_latm,pcm_s16le,pcm_s16be,pcm_s24le,pcm_u8,pcm_f32le,cook,sipr,ra_144,ra_288,musepack7,musepack8,dsd_lsbf,dsd_msbf,dsd_lsbf_planar,dsd_msbf_planar"
PARSERS="vorbis,opus,flac,aac,aac_latm,mpegaudio,cook"
LIBS=(avutil avcodec avformat swresample)
# --- 1. Source: clone shallow at the tag, verify the pinned commit ---
if [ ! -d ffmpeg ]; then
echo ">>> clone FFmpeg $TAG"
git clone --depth 1 --branch "$TAG" https://github.com/FFmpeg/FFmpeg.git ffmpeg
fi
ACTUAL_COMMIT=$(git -C ffmpeg rev-parse HEAD)
if [ "$ACTUAL_COMMIT" != "$PINNED_COMMIT" ]; then
echo "!!! source pin mismatch: HEAD=$ACTUAL_COMMIT expected=$PINNED_COMMIT" >&2
exit 1
fi
echo ">>> source verified: $TAG @ $ACTUAL_COMMIT"
CONFIGURE_COMMON=(
--enable-cross-compile --target-os=darwin --arch=arm64
--enable-shared --disable-static --disable-programs --disable-doc
--disable-everything --disable-avdevice --disable-swscale
--disable-avfilter --disable-postproc --disable-network
--enable-avformat --enable-avcodec --enable-avutil --enable-swresample
--enable-protocol=file
--enable-demuxer="$DEMUXERS" --enable-decoder="$DECODERS" --enable-parser="$PARSERS"
)
build_arch () { # $1=sdk $2=minflag $3=outdir
local SDK=$1 MINFLAG=$2 OUT=$3
local SYSROOT; SYSROOT=$(xcrun -sdk "$SDK" --show-sdk-path)
echo ">>> configure ($SDK)"
( cd ffmpeg && make distclean >/dev/null 2>&1 || true
./configure --prefix="$OUT" \
--cc="xcrun -sdk $SDK clang" --as="xcrun -sdk $SDK clang" \
--sysroot="$SYSROOT" \
--extra-cflags="-arch arm64 $MINFLAG -fno-stack-check" \
--extra-ldflags="-arch arm64 $MINFLAG" \
"${CONFIGURE_COMMON[@]}" > "$ROOT/configure-$SDK.log" 2>&1
make -j"$(sysctl -n hw.ncpu)" > "$ROOT/make-$SDK.log" 2>&1
make install >> "$ROOT/make-$SDK.log" 2>&1 )
echo ">>> $SDK done"
}
if [ "${1:-}" != "--package-only" ]; then
rm -rf "$ROOT/out"
build_arch iphoneos "-mios-version-min=$MIN_IOS" "$ROOT/out/ios-arm64"
build_arch iphonesimulator "-mios-simulator-version-min=$MIN_IOS" "$ROOT/out/sim-arm64"
fi
# --- 2. Package: dylib -> framework (install names via @rpath) -> xcframework ---
pick_dylib () { ls "$1"/lib/lib$2.*.dylib | grep -E "lib$2\.[0-9]+\.[0-9]+\.[0-9]+\.dylib" | head -1; }
make_framework () { # $1=srcdir $2=lib $3=fwroot
local src fw bin dep oldref
src=$(pick_dylib "$1" "$2")
fw="$3/lib$2.framework"; rm -rf "$fw"; mkdir -p "$fw"
bin="$fw/lib$2"
cp "$src" "$bin"
install_name_tool -id "@rpath/lib$2.framework/lib$2" "$bin"
# Rewrite EVERY sibling reference (absolute build path OR @rpath form) —
# absolute paths load on the simulator but crash dyld on a real device.
for dep in "${LIBS[@]}"; do
oldref=$(otool -L "$bin" | awk '{print $1}' | grep -E "(^|/)lib$dep\.[0-9]+\.dylib$" | head -1 || true)
[ -n "$oldref" ] && install_name_tool -change "$oldref" "@rpath/lib$dep.framework/lib$dep" "$bin"
done
/usr/libexec/PlistBuddy -c "Add :CFBundleIdentifier string org.ffmpeg.lib$2" \
-c "Add :CFBundleExecutable string lib$2" -c "Add :CFBundleName string lib$2" \
-c "Add :CFBundlePackageType string FMWK" -c "Add :CFBundleVersion string 1.0" \
-c "Add :CFBundleShortVersionString string 1.0" -c "Add :MinimumOSVersion string $MIN_IOS" \
"$fw/Info.plist" >/dev/null
codesign -f -s - "$bin" >/dev/null 2>&1 || true
# Gate: no absolute build paths may survive into the binary (skip otool's
# first line — it's the file path itself and would always match).
if otool -L "$bin" | tail -n +2 | grep -q "/Users"; then
echo "!!! absolute path leaked into lib$2" >&2; exit 1
fi
}
rm -rf "$ROOT/frameworks" "$ROOT/xcframeworks"
for lib in "${LIBS[@]}"; do
make_framework "$ROOT/out/ios-arm64" "$lib" "$ROOT/frameworks/ios-arm64"
make_framework "$ROOT/out/sim-arm64" "$lib" "$ROOT/frameworks/sim-arm64"
done
mkdir -p "$ROOT/xcframeworks"
for lib in "${LIBS[@]}"; do
xcodebuild -create-xcframework \
-framework "$ROOT/frameworks/ios-arm64/lib$lib.framework" \
-framework "$ROOT/frameworks/sim-arm64/lib$lib.framework" \
-output "$ROOT/xcframeworks/lib$lib.xcframework" > "$ROOT/xcf-$lib.log" 2>&1
done
# --- 3. Install into Vendor/ + record provenance ---
VENDOR="$REPO_ROOT/Vendor/FFmpeg"
rm -rf "$VENDOR/xcframeworks" "$VENDOR/include"
mkdir -p "$VENDOR/xcframeworks" "$VENDOR/include"
cp -R "$ROOT/xcframeworks/"*.xcframework "$VENDOR/xcframeworks/"
for hdr in libavcodec libavformat libavutil libswresample; do
cp -R "$ROOT/out/ios-arm64/include/$hdr" "$VENDOR/include/$hdr"
done
cp ffmpeg/COPYING.LGPLv2.1 "$VENDOR/COPYING.LGPLv2.1"
# Record the exact configure line and per-framework hashes.
grep -m1 "configure" "$ROOT/configure-iphoneos.log" > "$VENDOR/CONFIGURE.txt" 2>/dev/null || true
( cd ffmpeg && ./configure --help >/dev/null 2>&1 || true )
{
echo "tag: $TAG"
echo "commit: $ACTUAL_COMMIT"
echo "min_ios: $MIN_IOS"
echo "demuxers: $DEMUXERS"
echo "decoders: $DECODERS"
echo "parsers: $PARSERS"
echo "flags: -fno-stack-check (FFmpeg asm vs clang stack probing on Apple targets)"
} > "$VENDOR/PROVENANCE.txt"
echo ">>> BUILD+PACKAGE+INSTALL OK ($TAG @ $ACTUAL_COMMIT)"
The full LGPL v2.1 text ships inside the app (Settings → Third-party licenses) and is available at gnu.org. Relinking: because the libraries are dynamically linked, you may replace them in your own copy of the app bundle with your own builds of the same library versions.
Questions or a request for this source by other means: contact@ownplace.net.