Using ffmpeg to merge two audio file and one video file with control volume?

Viewed 1967

I want to use ffmpeg to merge 2 audio files with one video file to create one video file, but in audio file I want to control the volume level of each file.

What should I do ?

ffmpeg -i video.mp4 -i input1.mp3 -i input2.mp3
-filter_complex "[1]volume=0.5,pan=2c[a];[2]volume=0.7,pan=2c[b];[a][b]amix=duration=shortest"
-ac 2 -c:a libmp3lame -q:v 0 output.mp4
2 Answers

This is how I did that. First merging the input audio files using the below method.

private fun mergeAudios() {
    //ffmpeg -i one.mp3 -i two.mp3 -shortest -filter_complex \
    //"[0:a]adelay=10000|10000,volume=0.4[a0]; \
    // [1:a]volume=5.0[a1]; \
    // [a0][a1]amix=inputs=2[out]" \
    // -map "[out]" -ac 2 -c:a libfdk_aac output.m4a
    val finalAudio =
        File(Environment.getExternalStorageDirectory().absolutePath + "/" + System.currentTimeMillis() + ".mp3")
    val command = arrayOf(
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/2.mp3",
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/1543575307959.mp3",
        "-shortest",
        "-filter_complex",
        "[0:a]volume=0.4[a0];[1:a]volume=5.0[a1];[a0][a1]amix=inputs=2:duration=shortest",
        finalAudio.absolutePath
    )
    Log.d("ffmpeg", command.contentDeepToString())

    ffmpeg.execute(command, object : ExecuteBinaryResponseHandler() {
        override fun onFinish() {
            super.onFinish()
        }

        override fun onSuccess(message: String?) {
            super.onSuccess(message)
            Log.d("ffmpeg", "onSuccess ")

        }

        override fun onFailure(message: String?) {
            super.onFailure(message)
            Log.d("ffmpeg", "failure " + message)

        }

        override fun onProgress(message: String?) {
            super.onProgress(message)
            Log.d("ffmpeg", "progress " + message)

        }

        override fun onStart() {
            super.onStart()
        }
    })

}

And then merging the merged audio file with the video file.

private fun mergeAudioVideo() {
    val finalVideo =
        File(Environment.getExternalStorageDirectory().absolutePath + "/" + System.currentTimeMillis() + ".mp4")
    //ffmpeg -i video.mp4 -i audio.wav \
    //-c:v copy -c:a aac -strict experimental \
    //-map 0:v:0 -map 1:a:0 output.mp4
    val command = arrayOf(
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/2.mp4",
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/1543577399776.mp3"
        ,
        "-c:v",
        "copy",
        "-c:a",
        "aac",
        "-strict",
        "experimental",
        "-map",
        "0:v:0",
        "-map",
        "1:a:0",
        finalVideo.absolutePath
    )
    ffmpeg.execute(command, object : ExecuteBinaryResponseHandler() {
        override fun onFinish() {
            super.onFinish()
        }

        override fun onSuccess(message: String?) {
            super.onSuccess(message)
            Log.d("ffmpeg", "onSuccess ")

        }

        override fun onFailure(message: String?) {
            super.onFailure(message)
            Log.d("ffmpeg", "failure " + message)

        }

        override fun onProgress(message: String?) {
            super.onProgress(message)
            Log.d("ffmpeg", "progress " + message)

        }

        override fun onStart() {
            super.onStart()
        }
    })


}

Try this if it works for you. You might need some additional flags as your video has no audio files. If the command in the method doesn't work for you, try removing the -map argument for the audio flag

For a single command, this might work. I don't have the complete project to test it now so can't confirm for this one.

fun mergeAudioVideoDirectly(){
    val finalVideo =
        File(Environment.getExternalStorageDirectory().absolutePath + "/" + System.currentTimeMillis() + ".mp4")
    //ffmpeg -i <input1> -i <input2> -filter_complex "[0:a:0][1:a:0]amix[outa]" -map "[0:v:0]" -map ["outa"] <output>
    val command = arrayOf(
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/2.mp4",
        "-i",
        Environment.getExternalStorageDirectory().absolutePath + "/1.mp3",
        "-filter_complex",
        "[0:a:0][1:a:0]amix[outa]",
        "-map",
        "0:v:0",
        "-map",
        "[outa]",
        finalVideo.absolutePath
    )
    Log.d("ffmpeg ","command "+command.contentDeepToString())
    ffmpeg.execute(command, object : ExecuteBinaryResponseHandler() {
        override fun onFinish() {
            super.onFinish()
        }

        override fun onSuccess(message: String?) {
            super.onSuccess(message)
            Log.d("ffmpeg", "onSuccess ")

        }

        override fun onFailure(message: String?) {
            super.onFailure(message)
            Log.d("ffmpeg", "failure " + message)

        }

        override fun onProgress(message: String?) {
            super.onProgress(message)
        }

        override fun onStart() {
            super.onStart()
        }
    })
}

Please try the below command to mix audio video and volume setting

fun videoMixWithAudio(isNeedAudioCropped: Boolean): Array<String?> {
        val cmdList = ArrayList<String>()
        var cmds: Array<String?>? = null
        try {
            cmdList.add("-y")
            cmdList.add("-ss")
            cmdList.add(startVideoDuration.toString())
            cmdList.add("-t")
            cmdList.add(endVideoDuration.toString())
            cmdList.add("-i")
            cmdList.add(videoPath)
            cmdList.add("-ss")
            if (!isNeedAudioCropped) {
                cmdList.add("0")
            } else {
                cmdList.add(startAudioDuration.toString())
            }
            cmdList.add("-t")
            cmdList.add(endVideoDuration.toString())

            cmdList.add("-stream_loop")
            cmdList.add("-1")

            cmdList.add("-i")
            cmdList.add(audioPath)

            if (videovolume == -1f && audiovolume > -1) {
                cmdList.add("-c:v")
                if (startVideoDuration > 0) {
                    cmdList.add("mpeg4")
                    cmdList.add("-b:v")
                    cmdList.add("2304000")
                } else {
                    cmdList.add("copy")
                }
                cmdList.add("-c:a")
                cmdList.add("aac")
                cmdList.add("-map")
                cmdList.add("1:a:0")
                cmdList.add("-map")
                cmdList.add("0:v:0")
                cmdList.add("-strict")
                cmdList.add("-2")
                if (audiovolume < 0.99 || audiovolume > 1.01) {
                    cmdList.add("-vol")
                    cmdList.add((audiovolume * 100).toInt().toString())
                }
            }else{
                cmdList.add("-c:v")
                if (startVideoDuration > 0) {
                    cmdList.add("mpeg4")
                    cmdList.add("-b:v")
                    cmdList.add("2304000")
                } else {
                    cmdList.add("copy")
                }
                cmdList.add("-map")
                cmdList.add("0:v:0")
                cmdList.add("-strict")
                cmdList.add("-2")
                cmdList.add("-filter_complex")
                cmdList.add(
                    String.format(
                        "[0:a]aformat=sample_fmts=fltp:sample_rates=48000:channel_layouts=stereo,volume=%f[a0];" +
                                "[1:a]aformat=sample_fmts=fltp:sample_rates=48000:channel_layouts=stereo,volume=%f[a1];" +
                                "[a0][a1]amix=inputs=2:duration=first[aout]",
                        videovolume,
                        audiovolume
                    )
                )
                cmdList.add("-map")
                cmdList.add("[aout]")
            }

            cmdList.add("-b:a")
            cmdList.add("128000")
            cmdList.add("-ac")
            cmdList.add("2")
            cmdList.add("-ar")
            cmdList.add("44100")
            cmdList.add("-movflags")
            cmdList.add("faststart")
            cmdList.add("-preset")
            cmdList.add("ultrafast")
            cmdList.add(outputpath)

            cmds = arrayOfNulls<String>(cmdList.size)
            cmdList.toArray(cmds)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return cmds!!
    }
Related