javaandroidgradleffmpegrepository

How to import FFmpeg into Android project


I'm trying to convert series of images into video. For that I'm adding FFmpeg into my Android project. However it is not adding properly, so I can't import class FFmpeg into the code. in the statement "int rc = FFmpeg.execute(command);" FFmpeg is highlighted in red.

I think something wrong with libraries. Could you please give suggestion how import libraries correctly?

My Manifest file below

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/Theme.TimelapseLite"
    tools:targetApi="31">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

My settings.gradle file

pluginManagement {
repositories {
    google()
    mavenCentral()
    gradlePluginPortal()
}

}

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
    google()
    mavenCentral()
}

} rootProject.name = "TimelapseLite" include ':app'

My build.gradle file

plugins {
    id 'com.android.application'
}

android {
    namespace 'ae.vpdev.timelapselite'
    compileSdk 33

defaultConfig {
    applicationId "ae.vpdev.timelapselite"
    minSdk 26
    targetSdk 33
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

}

dependencies {

implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.arthenica:mobile-ffmpeg-full:4.5.LTS'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

}

My code in MainActivity

private void convertImagesToVideo() {
    StringBuilder imageListFileContent = new StringBuilder();
    for (Uri imageUri : selectedImages) {
        imageListFileContent.append("file '").append(imageUri.getPath()).append("'\n");
    }

    try {
        File imageListFile = new File(getCacheDir(), "image_list.txt");
        FileWriter writer = new FileWriter(imageListFile);
        writer.append(imageListFileContent.toString());
        writer.flush();
        writer.close();

        File outputFile = new File(getExternalFilesDir(null), "output_video.mp4");
        String outputFilePath = outputFile.getAbsolutePath();

        String command = "-f concat -safe 0 -i " + imageListFile.getAbsolutePath() +
                " -vf \"scale=-2:720\" -r 30 -c:v libx264 -pix_fmt yuv420p " + outputFilePath;

        int rc = FFmpeg.execute(command);

        if (rc == RETURN_CODE_SUCCESS) {
            Log.d("FFmpeg", "Video conversion completed successfully");
            // Now you can use the outputFilePath to play or share the video
        } else {
            Log.d("FFmpeg", "Video conversion failed");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Solution

  • I personally would not prefer to add the full FFMPEG SDK, as it increases the app size exponentially, however using Arthenica's FFMPEG-KIT seems the easiest way to get FFMPEG into a project

    implementation "com.arthenica:ffmpeg-kit-min-gpl:5.1.LTS"
    

    This new FFMPEG-KIT not only has a reduction in size, but the commands also execute quicker and have better async support and much easier implementation.

    To use you just have to import

    import com.arthenica.ffmpegkit.FFmpegKit
    import com.arthenica.ffmpegkit.ReturnCode
    

    and then :

    FFmpegKit.executeAsync(cmdString , {
        when {
            ReturnCode.isSuccess(it.returnCode) -> {
                println("FFMPEG SUCCESS :${it.state.name}")
            }
    
            ReturnCode.isCancel(it.returnCode) -> {
                println("FFMPEG CANCELLED :${it.returnCode}")
            }
    
            it.returnCode.isValueError -> {
                println("FFMPEG ERROR :${it.logs.last()}")
            }
        }
    } , {
        println("FFMEPG LOG :${it.message}")
    } , {
        println("FFMEPG STATS :${it.speed}")
    })
    

    here cmdString, is a string of commands, your commands should work but the only issue I ran into was that I had to use -y -i instead of -f which seemed to run the commands.