Use this library which supports targetSdkVersion 29.
implementation 'com.arthenica:mobile-ffmpeg-video:4.4'
Command used for video compression:
val complexCommand = arrayOf( "-y", "-i", inputPath!!, "-s", "640x480", "-r", "25", "-vcodec", "mpeg4", "-b:v", "1000k", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputFilePath )
Compression method:
private fun execFFmpegBinary(command: Array<String>, inputPath: String?, listener: CompressionListener?, outputFilePath: String) { Config.enableLogCallback { message -> Log.e(Config.TAG, message.text) } Config.enableStatisticsCallback { newStatistics -> Log.e( Config.TAG, String.format( "frame: %d, time: %d", newStatistics.videoFrameNumber, newStatistics.time ) ) Log.d( TAG, "Started command : ffmpeg " + Arrays.toString(command) ) val videoLength = inputPath?.let { VideoUtils.getVideoDuration(it) } Log.d(TAG, "execFFmpegBinary: Video Length : $videoLength") val progress: Float = java.lang.String.valueOf(newStatistics.time).toFloat() / videoLength!! val progressFinal = progress * 100 Log.d(TAG, "Video Length: $progressFinal") Log.d( Config.TAG, java.lang.String.format( "frame: %d, time: %d", newStatistics.videoFrameNumber, newStatistics.time ) ) Log.d( Config.TAG, java.lang.String.format( "Quality: %f, time: %f", newStatistics.videoQuality, newStatistics.videoFps ) ) //progressDialog.setProgress(progressFinal.toInt()) //val adjustProgress = progressFinal/1.5f Log.d(TAG, "execFFmpegBinary: Progress: ${progressFinal.toInt()}") listener?.onProgress(progressFinal.toInt()) Log.d(TAG, "progress : $newStatistics") } Log.d( TAG, "Started command : ffmpeg " + Arrays.toString(command) ) /* progressDialog.setMessage("Processing...") progressDialog.show()*/ val executionId = com.arthenica.mobileffmpeg.FFmpeg.executeAsync( command ) { executionId1: Long, returnCode: Int -> if (returnCode == RETURN_CODE_SUCCESS) { Log.d( TAG, "Finished command : ffmpeg " + Arrays.toString(command) ) listener?.compressionFinished(SUCCESS, true, fileOutputPath = outputFilePath) } else if (returnCode == Config.RETURN_CODE_CANCEL) { Log.e( TAG, "Async command execution cancelled by user." ) listener?.onFailure(String.format( "Async command execution cancelled by user." )) //if (progressDialog != null) progressDialog.dismiss() } else { Log.e( TAG, String.format( "Async command execution failed with returnCode=%d.", returnCode ) ) listener?.onFailure(String.format( "Async command execution failed with returnCode=%d.", returnCode )) // if (progressDialog != null) progressDialog.dismiss() } } Log.e(TAG, "execFFmpegMergeVideo executionId-$executionId") }
Compression Listener:
interface CompressionListener { fun compressionFinished( status: Int, isVideo: Boolean, fileOutputPath: String? ) fun onFailure(message: String?) fun onProgress(progress: Int) }
Call using:
execFFmpegBinary(complexCommand, inputPath, listener, outputFilePath)