Gradle Dependency
implementation "com.writingminds:FFmpegAndroid:0.3.2"
Code
Command to concate two videos side by side into one
val cmd : arrayOf("-y", "-i", videoFile!!.path, "-i", videoFileTwo!!.path, "-filter_complex", "hstack", outputFile.path)
Command to append two videos (one after another) into one
val cmd : arrayOf("-y", "-i", videoFile!!.path, "-i", videoFileTwo!!.path, "-strict", "experimental", "-filter_complex", "[0:v]scale=iw*min(1920/iw\\,1080/ih):ih*min(1920/iw\\,1080/ih), pad=1920:1080:(1920-iw*min(1920/iw\\,1080/ih))/2:(1080-ih*min(1920/iw\\,1080/ih))/2,setsar=1:1[v0];[1:v] scale=iw*min(1920/iw\\,1080/ih):ih*min(1920/iw\\,1080/ih), pad=1920:1080:(1920-iw*min(1920/iw\\,1080/ih))/2:(1080-ih*min(1920/iw\\,1080/ih))/2,setsar=1:1[v1];[v0][0:a][v1][1:a] concat=n=2:v=1:a=1", "-ab", "48000", "-ac", "2", "-ar", "22050", "-s", "1920x1080", "-vcodec", "libx264", "-crf", "27", "-q", "4", "-preset", "ultrafast", outputFile.path)
Note :
"videoFile" is your first video path.
"videoFileTwo" is your second video path.
"outputFile" is your combined video path which is our final output path
To create output path of video
fun createVideoPath(context: Context): File { val timeStamp: String = SimpleDateFormat(Constant.DATE_FORMAT, Locale.getDefault()).format(Date()) val imageFileName: String = "APP_NAME_"+ timeStamp + "_" val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES) if (storageDir != null) { if (!storageDir.exists()) storageDir.mkdirs() } return File.createTempFile(imageFileName, Constant.VIDEO_FORMAT, storageDir) }
Code to execute command
try { FFmpeg.getInstance(context).execute(cmd, object : ExecuteBinaryResponseHandler() { override fun onStart() { } override fun onProgress(message: String?) { callback!!.onProgress(message!!) } override fun onSuccess(message: String?) { callback!!.onSuccess(outputFile) } override fun onFailure(message: String?) { if (outputFile.exists()) { outputFile.delete() } callback!!.onFailure(IOException(message)) } override fun onFinish() { callback!!.onFinish() } }) } catch (e: Exception) { } catch (e2: FFmpegCommandAlreadyRunningException) { }