使用ffmpeg合并具有控制音量的两个音频文件和一个视频文件?

时间:2018-12-18 08:26:17

标签: android ffmpeg

我想使用ffmpeg将2个音频文件与一个视频文件合并以创建一个视频文件,但是在音频文件中,我想控制每个文件的音量。

我该怎么办?

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 个答案:

答案 0 :(得分:0)

这就是我这样做的方式。 首先使用以下方法合并输入的音频文件。

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

}

然后将合并的音频文件与视频文件合并。

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


}

如果适合您,请尝试此操作。您的视频没有音频文件,因此可能需要一些其他标志。如果该方法中的命令对您不起作用,请尝试删除音频标志的-map参数

对于单个命令,这可能有效。我现在没有完整的项目来对其进行测试,因此无法确认这一点。

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

答案 1 :(得分:0)

请尝试以下命令混合音频视频和音量设置

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!!
    }