Search code examples
androidffmpegandroid-ffmpeg

How to use Hardware codec during video compression in Android


I was wondering how to use hardware acceleration in the best way to compress a video on Android. I've tried Transformer by ExoPlayer and is quite slow.

With ffmpegKit unfortunately libopenh264 is quite slow (and doesn't use hardware codec) and I'm not able to make h264_mediacodec work. Any idea on how to make the mediacodec work?

This is the code I'm using right now for the tests but it fails with mediacodec (generic error). I've compiled manually FFMpegKit to add mediacodec already.

companion object {
    private const val VIDEO_WIDTH = 1080
    private const val VIDEO_HEIGHT = 1920
    private const val BITRATE_MBS = 7 * 1000000
    private const val COMPRESSION_FILE_NAME = "compression"
    private const val VIDEO_EXTENSION = ".mp4"
}

suspend fun compressVideo(videoUri: Uri): String? = withContext(defaultDispatcher) {
    val tempInputFile = copyUriToFile(context, videoUri)
    val outputFile = File.createTempFile(COMPRESSION_FILE_NAME, VIDEO_EXTENSION, context.cacheDir)
    val outputPath = outputFile.absolutePath

    val cmd = mutableListOf(
        "-y",
        "-i", tempInputFile.absolutePath,
        "-vf", "scale=w=$VIDEO_WIDTH:h=$VIDEO_HEIGHT:force_original_aspect_ratio=decrease",
        "-c:v", "h264_mediacodec",
        "-b:v", "$BITRATE_MBS",
        outputPath
    )

    val session: FFmpegSession = FFmpegKit.execute(cmd.joinToString(" "))

    tempInputFile.delete()

    return@withContext if (ReturnCode.isSuccess(session.returnCode)) {
        outputPath
    } else {
        FirebaseCrashlytics.getInstance().recordException(Exception("FFmpeg compression failed: ${session.allLogsAsString}"))
        null
    }
}

Solution

  • What I've found so far is this library: https://github.com/AbedElazizShe/LightCompressor

    That is the code that Telegram uses for compressing videos and relies on MediaCodec. I think it's hard to have something better than this, except for ffmpeg with mediacodec (that unfortunately I'm not able to make it run).