【问题标题】:Using ffmpeg to merge two audio file and one video file with control volume?使用ffmpeg合并两个音频文件和一个带有控制音量的视频文件?
【发布时间】:2021-06-23 17:42:49
【问题描述】:

我想使用 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

【问题讨论】:

  • 因此您将拥有 3 个音频文件,其中一个也来自视频。我所做的是分别合并音频文件,然后将其添加到视频文件中。
  • 我学习了如何更改合并2个音频文件的音量以及如何将2个音频文件与视频文件合并并创建上述公式,但是执行时出现错误。跨度>
  • 我的视频文件没有音频

标签: android ffmpeg


【解决方案1】:

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

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

【讨论】:

  • 我关注这个stackoverflow.com/questions/50168993/…。作为您的解决方案,我们可以将其合并为一个命令?
  • @phongvan 添加了另一种直接合并的方法。但我不确定这是否可行
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 2016-05-30
    • 2013-05-22
    相关资源
    最近更新 更多