Skip to content

Compressing a video#

Applies to LUNA ID for Android only.

To compress a video, you need to integrate FFmpegKit into your Android project:

1․ Add the JitPack repository

In your settings.gradle.kts file, include the JitPack repository as follows:

pluginManagement {
    repositories {
        google()
        gradlePluginPortal()
        mavenCentral()
        maven("https://jitpack.io ")
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven("https://jitpack.io ")
    }
}

2․ Add the FFmpegKit Dependency

In your module's build.gradle.kts file (for example, app/build.gradle.kts), add the following dependency under dependencies:

dependencies {
    implementation("com.github.arthenica:ffmpeg-kit-min-gpl:6.0-2.LTS") // Minimal GPL version
    // For the full version, use:
    // implementation("com.github.arthenica:ffmpeg-kit-full-gpl:6.0-2.LTS")
}

3․ Sync your project

After adding the dependencies, sync your project with Gradle files.

In Android Studio, go to File > Sync Project with Gradle Files.

4․ Request permissions (if needed)

Add the necessary permissions to your AndroidManifest.xml file:

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

Note: If targeting Android 10 (API level 29) or higher, consider using the Storage Access Framework (SAF) instead of requesting direct storage permissions.

5․ Add the FFmpegUtils utility class

Create a utility class named FFmpegUtils to handle FFmpeg operations. Here's an example implementation:

package ru.visionlabs.sdk.lunacore.utils

import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.ReturnCode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object FFmpegUtils {

    /**
     * Compresses a video file using FFmpeg.
     *
     * @param inputPath The path to the input video file.
     * @param outputPath The path where the compressed video will be saved.
     * @param onSuccess Callback invoked on successful compression.
     * @param onFailure Callback invoked if an error occurs.
     */
    fun compressWithFFmpeg(
        inputPath: String,
        outputPath: String,
        onSuccess: () -> Unit,
        onFailure: (Throwable) -> Unit
    ) {
        val cmd = listOf(
            "-y", "-i", inputPath,
            "-vf", "scale=iw/2:ih/2", // Scale video resolution by half
            "-c:v", "libx264", "-b:v", "1M", "-preset", "fast", // Video codec settings
            "-c:a", "aac", "-b:a", "128k", // Audio codec settings
            outputPath
        )

        CoroutineScope(Dispatchers.IO).launch {
            try {
                val session = FFmpegKit.execute(cmd.joinToString(" "))
                if (ReturnCode.isSuccess(session.returnCode)) {
                    onSuccess()
                } else {
                    onFailure(
                        RuntimeException("FFmpeg failed: ${session.returnCode}\n${session.failStackTrace}")
                    )
                }
            } catch (e: Exception) {
                onFailure(e)
            }
        }
    }
}

6․ Use the utility in your activity or fragment

To compress a video, use the FFmpegUtils.compressWithFFmpeg method as shown below:

val input = "/sdcard/DCIM/input.mp4" // Path to the input video file
val output = cacheDir.resolve("compressed.mp4").absolutePath // Path to save the compressed video

FFmpegUtils.compressWithFFmpeg(
    inputPath = input,
    outputPath = output,
    onSuccess = {
        // Handle success (e.g., show a Toast or notify the user)
        println("Compression successful!")
    },
    onFailure = { err ->
        // Handle failure (e.g., log the error or show a message)
        println("Compression failed: ${err.message}")
    }
)