我想使用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
答案 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!!
}