The build scripts for the libmpv inside mpv_audio_kit. They compile mpv and FFmpeg without video, with a set of patches the package relies on (waveform, loudness scan, audio taps and more), for macOS, iOS, Android, Windows and Linux.
Everything runs from ./build, a terminal menu where you pick the targets and follow the builds.
git clone https://github.com/ales-drnz/libmpv-scripts
cd libmpv-scripts
./buildOn Windows use build.cmd. You need Go, plus Docker for Linux, Windows and Android, and Xcode for Apple targets.
| Platform | Architectures | File in builds/release/ |
|---|---|---|
| macOS | arm64 and x86_64 (universal) | libmpv_macos.xcframework.zip |
| iOS | arm64 device, arm64 and x86_64 simulator | libmpv_ios.xcframework.zip |
| Android | arm64-v8a, armeabi-v7a, x86_64 | libmpv_android-<abi>.so |
| Linux | x86_64, aarch64 | libmpv_linux-<arch>.so |
| Windows | x86_64, arm64 | libmpv_windows-<arch>.dll |
Each library exports only the mpv_* C API, plus the mak_pcm_* functions that feed live PCM to the mak-pcm protocol, and carries no video decoders. On Linux and Android its SONAME is libmpv_audio_kit.so, so it can live next to another plugin's libmpv. The Linux one needs glibc 2.31 or later and ALSA (libasound.so.2). It loads PipeWire and PulseAudio only when they are installed, through stubs made with Implib.so (vendored in tools/implib), and skips a PipeWire older than 0.3.57 in favour of PulseAudio, then ALSA.
The versions of mpv, FFmpeg and every other dependency are set in scripts/shared/_versions.sh, and scripts/shared/_sources.sha256 pins each source tarball by its SHA-256 and each git source (libplacebo, libsmb2, PipeWire) by the commit of its tag. A build also writes builds/release/manifest.json, with the versions, the compiled audio filters and the hash of every library.
| Tool | Needed for |
|---|---|
| Go | always, it runs ./build |
| Docker | Linux, Windows and Android (Android on macOS builds without it) |
| Xcode | macOS and iOS |
The Android NDK is downloaded by the build, you don't need to install it.
| Host | Targets |
|---|---|
| macOS | all of them |
| Linux | all except macOS and iOS |
| Windows | all except macOS and iOS |
Apple targets need a Mac, and Linux builds only for the host's own architecture. GitHub Actions builds everything, whatever you have.
Building needs only this repo. Everything it produces lands in builds/: the libraries and manifest.json in builds/release/, the logs in builds/logs/.
Run ./build. Arrow keys move, Space selects, Enter confirms, Q quits. The keys for each screen are listed at the bottom. There are three screens, switched with B, S and D.
Three tabs:
- Compile: pick platforms and architectures, then press Build. Each build shows its progress, time and warning count, and Enter opens its log.
- Tools: write
manifest.jsonfor the built libraries (Manifest), check them (Verify), and refresh the bundled CA certificates (Update CA). - Docker: see, build or delete the Docker images. The image a build needs is created automatically the first time.
Choose which audio decoders, audio filters and patches go into the build. Fewer decoders and filters make a smaller library, but a format you remove won't play. Your choices are saved separately from the defaults, and you can reset them at any time.
Every library in the build, with its version and license.
On a Mac with Xcode:
./build macos # universal xcframework
./build ios # device and simulator xcframework
./build macos-arm64 # one architectureBoth build in Docker. Linux builds natively on Ubuntu 20.04, for the glibc 2.31 floor, so an x86_64 host builds linux-x86_64 and an arm64 host builds linux-aarch64. Windows cross-compiles both architectures from any host:
./build linux-x86_64 # on an x86_64 host
./build windows # x86_64 and arm64On macOS it builds directly on the host, which is the fastest option. Elsewhere it builds in Docker. The Docker tab can force Docker on macOS too.
./build android # all three ABIs
./build android-arm64-v8a # one ABI./build accepts targets as arguments and runs them in order, stopping at the first failure:
./build all # everything this host can build, then the manifest
./build macos verify # build macOS, then verify it
./build list # every targetThese variables are passed to the Docker builds:
| Variable | Effect |
|---|---|
JOBS=N |
parallel jobs, all cores by default |
ENABLE_LTO_DEPS=0 |
turn off link-time optimization for the dependencies |
FORCE_DOWNLOAD=1 |
download the sources again |
KEEP_BUILD=1 |
keep the build folders |
WIPE_ALL=1 |
also delete the downloaded sources |
STRICT_SOURCES=1 |
stop on a source that is not pinned, as CI does |
RECORD_SOURCES=<file> |
append the hash of every unpinned source to a file |
To build another version of a dependency, set MPV_VERSION, FFMPEG_VERSION and so on (see scripts/shared/_versions.sh).
Every push to a release/ branch runs .github/workflows/build.yml, which builds all nine libraries on GitHub's runners, Apple included, with STRICT_SOURCES=1. The run ends with a libmpv-release artifact holding the libraries and manifest.json, then checks them as in 4.3. It also plays a tone with the Linux x86_64 library in a bare Debian 11 container, without PipeWire and PulseAudio, and runs the patch tests of 4.3. A build stopped by an unpinned source uploads the line to add as an unpinned-sources-<job> artifact.
From 0.5.0, mpv_audio_kit gets libmpv through a build hook (hook/build.dart). When an app builds, the hook downloads the library for the target from the package's libmpv-rN GitHub release and checks its SHA-256. To point the package at a release, run this in mpv_audio_kit:
scripts/update_libmpv.sh r19 # a published release
scripts/update_libmpv.sh r19 path/to/manifest.json # before publishing itIt writes the release and the hashes from manifest.json into the hook.
To try a local build in an app, point the hook at the file in the app's pubspec.yaml. The file is bundled as it is, without a checksum:
hooks:
user_defines:
mpv_audio_kit:
libmpv: path/to/libmpv_linux-x86_64.soThe Manifest action in the Tools tab writes builds/release/manifest.json for a local build, ready for update_libmpv.sh.
./build verify checks every library in builds/release/: architecture, exported API, the patched mpv properties, the included decoders and filters, the spdif muxer and the httpproxy, https and tls protocols, that no video code slipped in, and the libraries it depends on. On Linux and Android it also checks the SONAME, that there is no DT_RELR, the 16 KB alignment of the 64 bit Android libraries and the glibc 2.31 floor. Where the host can load it, it also opens the library and calls into it. The report has one row per library, and Enter shows the full log.
The patches have tests of their own: bash verify/tests/native/run.sh <work dir> builds a debug libmpv with AddressSanitizer against the system FFmpeg and runs the C tests of the patched mpv, then the tests of the patch scripts. It needs meson, ninja, the ffmpeg command and the FFmpeg development files, and takes a few minutes.
bash verify/tests/network_test.sh <work dir> builds libsmb2 and a minimal FFmpeg with AddressSanitizer and the SMB and TLS patches, then checks them against a local impacket SMB server and openssl s_server: the URL parsing, a stop while the server stalls, the connect deadline and the embedded CA roots. It needs cmake, ninja, the OpenSSL development files and impacket for the python in SMB_PYTHON, and takes about two minutes.
- Build all nine libraries, usually by pushing a
release/branch (see 3.5). - Create the
libmpv-rNrelease onmpv_audio_kitand upload the libraries andmanifest.json. - In
mpv_audio_kit, runscripts/update_libmpv.sh rN.
./build is a small Go program (Bubble Tea) that runs the shell scripts in scripts/, one per platform. Apple targets build with Xcode on the host. Linux, Windows and Android build inside a Docker image from docker/Dockerfile, which has one stage per platform, so you only keep the toolchains you use.
Each build downloads the pinned sources, applies the patches in patches/ to mpv and FFmpeg, compiles only the audio parts, and strips the library down to the mpv_* and mak_pcm_* API. Every patch finds its place by exact text and stops the build if upstream has changed underneath it.
- "Go not found": install Go and run again.
- A Linux, Windows or Android build fails right away: Docker isn't running.
- macOS and iOS are greyed out: they need a Mac with Xcode. GitHub Actions can build them instead.
- The first Docker build is slow: it is building the image, later builds reuse it.
- "Unpinned source": a download is not in
scripts/shared/_sources.sha256. Add the line the error prints, or build withoutSTRICT_SOURCES=1and collect the lines withRECORD_SOURCES. - "the Linux build is native-only": Linux builds only for the host's architecture. Use a host of the other architecture, or GitHub Actions.
- Android in Docker is slow on Apple Silicon: the NDK is x86_64 only. Build on the host (the default), or turn on Rosetta in Docker Desktop.
The build pipeline, the Go TUI and the patches for mpv and FFmpeg were written with Claude Code.
Developed by Alessandro Di Ronza
