libmpv for Android

mpv for Android, as one dependency.

mpv, FFmpeg and libplacebo, built for every Android ABI and published to Maven Central with a small Kotlin wrapper. It's the player engine behind Ephyra.

Latest: 1.1.0, with mpv 0.42.0 and FFmpeg 9.0.2. GPL-3.0-or-later. Android 8.0 or newer.

build.gradle.kts

dependencies {
    implementation("io.github.midasvo:libmpv:1.1.0")
}

Kotlin

import dev.jdtech.mpv.MPVLib

val mpv = MPVLib.create(context) ?: return
mpv.setOptionString("gpu-context", "android")
mpv.setOptionString("hwdec", "mediacodec")
mpv.init()

// once the Surface exists
mpv.attachSurface(holder.surface)
mpv.setOptionString("force-window", "yes")
mpv.setOptionString("vo", "gpu")
mpv.command(arrayOf("loadfile", url))

// when the player goes away
mpv.destroy()

Use it

It's on Maven Central, so there's no extra repository to add. One AAR holds the native libraries for arm64-v8a, armeabi-v7a, x86 and x86_64, and the Kotlin wrapper MPVLib.

New project

// settings.gradle.kts: mavenCentral() is usually there already
dependencies {
    implementation("io.github.midasvo:libmpv:1.1.0")
}

The wrapper creates an mpv instance, attaches it to a Surface, sets options and properties, sends commands, and passes mpv's events and log messages to your observers. Everything else is mpv itself: its manual is the reference for options, properties and commands.

Coming from dev.jdtech.mpv:libmpv

Change the coordinate and nothing else. The Kotlin package stays dev.jdtech.mpv, so your code compiles unchanged. Don't keep both: they ship the same native libraries under the same file names.

Two things changed in mpv 0.42 that a player notices:

  • http(s) goes through libcurl by default. curl-enabled=no brings back FFmpeg's own networking.
  • tls-verify defaults to yes, and the build has no CA bundle of its own.

What's inside 1.1.0

libmpv.so and the FFmpeg libraries are shared libraries. Everything else is statically linked into them.

Each release's notes list the exact versions, and every version lives in one file, depinfo.sh. Built with NDK 30 against Android API 37, minimum API 26.

New in 1.1.0: mpv 0.42.0 (was 0.41.0), FFmpeg 9.0.2 (was 8.1), and libplacebo 7.387.0, which fixes AV1 film grain on OpenGL ES.

LibraryVersionLicence
mpv0.42.0GPL-2.0-or-later
FFmpeg9.0.2GPL-3.0-or-later
libplacebo7.387.0LGPL-2.1-or-later
dav1d1.5.4BSD-2-Clause
libass0.17.5ISC
curl8.23.0curl
mbedtls3.6.7Apache-2.0
harfbuzz15.1.0Old MIT
freetype2.15.0FTL or GPL-2.0-or-later
fontconfig2.18.3fontconfig
fribidi1.0.18LGPL-2.1-or-later
libunibreak8.0Zlib
libxml22.15.4MIT
lua5.2.4MIT

Why a fork

This is a fork of jarnedemeulemeester/libmpv-android, the library Findroid uses. Upstream had already merged mpv 0.42 and FFmpeg 9, but there was no release with them yet, and Ephyra needed the libplacebo fix for AV1 film grain. So this fork publishes its own releases. It follows upstream rather than competing with it.

Close to upstream

A weekly workflow opens a pull request that merges upstream's main. The fork's own changes are a short list of files, so those merges stay trivial.

Current

Renovate proposes every new version of mpv, FFmpeg and the rest. CI builds all four ABIs on each one before it can be merged.

Tested in a real player

A release goes into Ephyra before anything else. 1.1.0 was played on a phone, on emulators and on a 32-bit Android TV box, including hardware-decoded 10-bit AV1.

Licence and source

The code in the repository is MIT. The AAR is effectively GPL-3.0-or-later, because libmpv.so links FFmpeg and other GPL components. An app that ships it has to show the licences and offer the source.

Source with every release

Each release attaches libmpv-<version>-sources.tar.xz: the repository at the tag plus every dependency as downloaded and patched. Link to it from your app and that part is covered.

Signed and reproducible

Releases are signed with a dedicated key that's published on keys.openpgp.org and keyserver.ubuntu.com. The build leaves the date out of libmpv.so, so two builds of the same tag can be compared byte for byte.