Logo
Android NDK Guide

Integrating FFmpeg 7+ with Kotlin via JNI

A complete, step-by-step visual guide to integrating pre-compiled FFmpeg 7 dynamic libraries (.so) into a modern Android project using CMake, JNI, and Jetpack Compose.

Step 1: Project Structure

Organize C/C++ headers and dynamic libraries

First, you need pre-compiled FFmpeg 7.x libraries for Android. Place the include folder (headers) and libs folder (.so files for arm64-v8a, etc.) into your app's app/src/main/cpp/ffmpeg directory.

Ensure your package name context matches your app setup. For this guide, we assume the app is com.papa.ffmpeg.

Directory Tree
  • app/src/main/
  • cpp/
  • ffmpeg/
  • include/ /* headers */
  • libs/
  • arm64-v8a/
  • libavcodec.so
  • libavutil.so
  • CMakeLists.txt
  • native-lib.cpp
  • java/com/papa/ffmpeg/
  • FFmpegHelper.kt
  • MainActivity.kt

Step 2: Build Configuration

Link the shared libraries in build scripts

1. app/build.gradle.kts

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
}

android {
    namespace = "com.papa.ffmpeg"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.papa.ffmpeg"
        minSdk = 24
        targetSdk = 34
        
        ndk {
            // Only package 64-bit to reduce APK size
            abiFilters += listOf("arm64-v8a") 
        }
    }
    
    // Configure CMake path and arguments
    externalNativeBuild {
        cmake {
            path = file("src/main/cpp/CMakeLists.txt")
            version = "3.22.1"
        }
    }
}

2. app/src/main/cpp/CMakeLists.txt

cmake_minimum_required(VERSION 3.22.1)
project("papa_ffmpeg")

# Define FFmpeg directory variable
set(FFMPEG_DIR ${CMAKE_SOURCE_DIR}/ffmpeg)
include_directories(${FFMPEG_DIR}/include)

# Import pre-compiled libavutil.so
add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION 
    ${FFMPEG_DIR}/libs/${ANDROID_ABI}/libavutil.so)

# Import pre-compiled libavcodec.so
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION 
    ${FFMPEG_DIR}/libs/${ANDROID_ABI}/libavcodec.so)

# Build your JNI bridge into papa_native
add_library(papa_native SHARED native-lib.cpp)

# Link libraries together (including Android log)
target_link_libraries(papa_native
    avutil
    avcodec
    log 
)

Step 3: C++ JNI Implementation

Bridge Kotlin with FFmpeg C API

native-lib.cpp
#include <jni.h>
#include <string>
#include <android/log.h>

// Android Logcat macros for easy debugging
#define LOG_TAG "PapaFFmpegNative"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

// FFmpeg is written in C, so we must wrap headers in extern "C"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}

// JNI Method matching: package com.papa.ffmpeg -> object FFmpegHelper -> fun getVersion()
extern "C" JNIEXPORT jstring JNICALL
Java_com_papa_ffmpeg_FFmpegHelper_getVersion(JNIEnv* env, jobject /* this */) {

    // Call FFmpeg API
const char* version = av_version_info();

    // Log to logcat
LOGI("FFmpeg is running! Version: %s", version);

    // Convert C string to Java string and return
return env->NewStringUTF(version);
}

Step 4: Kotlin & Jetpack Compose UI

Load the library and render the result on screen

FFmpegHelper.kt
package com.papa.ffmpeg

// Wrapper Object for JNI
object FFmpegHelper {
init {
        // Matches the library name in CMakeLists.txt
System.loadLibrary("papa_native")
}

    // External function mapped to C++
external fun getVersion(): String
}
MainActivity.kt
package com.papa.ffmpeg

import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FFmpegInfoScreen()
}
}
}

@Composable
fun FFmpegInfoScreen() {
var ffmpegVersion by remember { mutableStateOf("Fetching...") }

LaunchedEffect(Unit) {
        // Fetch via JNI when screen mounts
ffmpegVersion = FFmpegHelper.getVersion()
}

Column(modifier = Modifier.padding(24.dp)) {
Text(text = "Papa FFmpeg Integration")
Spacer(modifier = Modifier.height(16.dp))
Card {
Text(
text = "Core Version:\n$ffmpegVersion",
modifier = Modifier.padding(16.dp)
)
}
}
}
12:00

Papa FFmpeg Integration

Core Version:

7.0.1

JNI Call Successfully Executed

Simulated Render of Compose UI

Explore More#mobile-dev

Integrating FFmpeg 7+ with Kotlin via JNI

Article

A complete, step-by-step visual guide to integrating pre-compiled FFmpeg 7 dynamic libraries (.so) into a modern Android project using CMake, JNI, and Jetpack Compose.

Android FFmpeg + C++: Video Cropping and Filter Processing

Article

A detailed demonstration of how to use FFmpeg and C++ in an Android project to implement video cropping, filter processing, and progress callbacks.

Integrating OpenCV 4.x in Android Studio

Article

A detailed step-by-step guide on how to integrate OpenCV 4.x into an Android Studio project, configure CMake and JNI, and implement image processing features.

Using OpenCV for Image Sharpening in Android

Article

A detailed step-by-step guide on how to integrate OpenCV into an Android project and implement image sharpening functionality.

Android OpenCV + FFmpeg 7: Making Videos Clearer from Blurry

Article

A detailed demonstration of how to use OpenCV and FFmpeg 7 in an Android project for video processing, achieving clarity from blurriness.

FFmpeg Android + OpenSSL Compilation Guide

Article

A detailed step-by-step guide on how to compile FFmpeg from source and integrate OpenSSL on the Android platform for HTTPS streaming support.

FFmpeg Xcode + Swift Compilation Guide

Article

A detailed step-by-step guide on how to compile FFmpeg from source using Xcode and Swift on macOS, and integrate it into an iOS project.

Android Image Similarity Detection and Grouping

Article

A detailed demonstration of how to use OpenCV in an Android project to implement image similarity detection and grouping features.