NextLib is a library for adding ffmpeg codecs to Media3.
- Audio: Vorbis, Opus, Flac, Alac, pcm_mulaw, pcm_alaw, MP3, Amrnb, Amrwb, AAC, AC3, EAC3, dca, mlp, truehd
- Video: H.264, HEVC, VP8 and VP9 (FFmpeg built-in decoders), AV1 (dav1d)
Kotlin DSL:
dependencies {
implementation("io.github.anilbeesetti:nextlib-media3ext:INSERT_VERSION_HERE") // To add media3 software decoders and extensions
implementation("io.github.anilbeesetti:nextlib-mediainfo:INSERT_VERSION_HERE") // To get media info through ffmpeg
}Groovy DSL:
dependencies {
implementation "io.github.anilbeesetti:nextlib-media3ext:INSERT_VERSION_HERE" // To add media3 software decoders and extensions
implementation "io.github.anilbeesetti:nextlib-mediainfo:INSERT_VERSION_HERE" // To get media info through ffmpeg
}Use NextRenderersFactory with extension renderers enabled to make the bundled FFmpeg decoders
available to Media3. The factory retains DefaultRenderersFactory's default of OFF:
import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.ExoPlayer
import io.github.anilbeesetti.nextlib.media3ext.ffdecoder.NextRenderersFactory
// OFF: Do not add FFmpeg extension renderers.
// ON: Enable them at normal priority, after platform renderers.
// PREFER: Give FFmpeg extension renderers priority.
val renderersFactory = NextRenderersFactory(applicationContext)
.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
ExoPlayer.Builder(applicationContext)
.setRenderersFactory(renderersFactory)
.build()This controls renderer priority and capability fallback: ON allows FFmpeg when platform
renderers cannot support a format. It does not automatically recover from runtime decoder failures;
applications own error recovery.
Create a DecoderManager alongside NextRenderersFactory when the application needs to select
video and audio decoders while keeping the same ExoPlayer instance:
val decoderManager = DecoderManager()
val renderersFactory = NextRenderersFactory(applicationContext)
.setDecoderManager(decoderManager)
val player = ExoPlayer.Builder(applicationContext)
.setRenderersFactory(renderersFactory)
.build()
decoderManager.attach(player)
decoderManager.selectVideoDecoder(DecoderMode.HARDWARE)
decoderManager.selectAudioDecoder(DecoderMode.AUTO)
decoderManager.detach()
player.release()Installing a DecoderManager enables extension renderers at normal priority (ON) and MediaCodec
initialization fallback. Video and audio are selected independently. See
media3ext/DECODER_SWITCHING.md for mode behavior, lifecycle, and
application-owned error handling.
Use macOS or Linux (WSL on Windows), JDK 17+, make, curl, tar, and
pkg-config, Meson, Ninja, and NASM 2.14+ (brew install meson ninja nasm on
macOS; sudo apt-get install meson ninja-build nasm on Ubuntu). NASM is used for
both FFmpeg and dav1d's x86 assembly. Install Android CLI
and put android on PATH, or set ANDROID_CLI to its executable path.
Set sdk.dir in local.properties or export ANDROID_HOME to your Android SDK.
./gradlew assembleReleaseBoth modules depend on one :ffmpegSetup task, which installs missing NDK/CMake
packages with Android CLI and builds the four supported ABIs before CMake runs.
NDK and CMake versions come from gradle/libs.versions.toml. Existing SDK tools
are reused; Android CLI is only needed when a package is missing. Complete any
SDK license prompts during initial installation before running a headless build.
The build pins FFmpeg 9.0.1, mbedTLS 3.6.7 (the 3.6 LTS branch), and dav1d 1.5.4.
mbedTLS is built from its complete release archive and linked statically for
HTTPS/TLS support. The build statically links dav1d into FFmpeg's libavcodec.so
for every ABI, with assembly optimizations and both 8-bit and high-bit-depth AV1
support. AV1 uses the libdav1d decoder in Media3 and in media-info/thumbnail lookups.
Gradle tracks the setup script, tool versions, and generated output so unchanged builds skip FFmpeg. To force rebuilding it:
./gradlew :ffmpegSetup --rerun-tasksFor standalone use, export ANDROID_HOME and run bash ffmpeg/setup.sh (always
rebuilds). Run python3 ffmpeg/test_setup.py for setup regression checks without
SDK downloads or native compilation.
To verify AV1 decoding and seeking on a disposable ARM64 Android emulator, build
the library and run the native regression test (requires host FFmpeg with the
libsvtav1 encoder):
ANDROID_NDK_HOME=/path/to/sdk/ndk/25.2.9519653 ANDROID_SERIAL=emulator-5554 \
bash media3ext/src/test/cpp/run_av1_decoder_test.shThis checks decoder discovery by both name and codec ID, 8-bit and 10-bit output,
film-grain decoding, one output frame per sample with no delayed frames at EOS,
and decoding again after a seek/flush. AV1 uses dav1d's low-delay mode to match
Media3's SimpleDecoder input/output contract.
See AV1 verification for the Next Player playback checks and tested device coverage.
See FFmpeg and mbedTLS upgrade verification for the current dependency build, TLS, rotation metadata, and playback checks.