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
}
}
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).