如何使用ffmpeg将新的音频(非混合)添加到视频中?

254
我使用了以下命令:

```

ffmpeg -i video.avi -i audio.mp3 -vcodec codec -acodec codec output_video.avi -newaudio

在最新版本中,可以向视频添加新的音轨(不是混合)。

但是,我已经将ffmpeg更新到最新版本(ffmpeg version git-2012-06-16-809d71d),现在在这个版本中,参数-newaudio不起作用。

请告诉我如何使用ffmpeg向我的视频添加新的音轨(不是混合)。


@Kiquenet 是的,你说得对。答案已经给出了。只需阅读本主题即可。这个问题已经有5年了。 - Vetalll
1
你说添加新音频是指替换音频,对吗?我可能会编辑你的问题以澄清这一点。 - tommy.carstensen
在这个问题中,最好澄清你想要实现什么,添加新音频的上下文可能意味着(1)将audio.mp3中的音频流应用于输出文件(2)audio.mp3video.avi中的2个音频流共存于输出文件中,然后让应用程序在它们之间切换。 - Ham
10个回答

587

替换音频

diagram of audio stream replacement

ffmpeg -i video.mp4 -i audio.wav -map 0:v -map 1:a -c:v copy -shortest output.mp4
  • -map选项允许您手动选择流/轨道。有关更多信息,请参见FFmpeg Wiki: Map
  • 此示例使用-c:v copystream copy(复用)视频。不会重新编码视频,保留质量,处理速度快。
    • 如果输入音频格式与输出格式兼容,则将-c:v copy更改为-c copy以流式复制视频和音频
    • 如果要重新编码视频和音频,则删除-c:v copy / -c copy
  • -shortest选项将使输出与最短输入的持续时间相同。

添加音频

diagram of audio stream addition

ffmpeg -i video.mkv -i audio.mp3 -map 0 -map 1:a -c:v copy -shortest output.mkv
  • -map选项允许您手动选择流/轨道。有关更多信息,请参见FFmpeg Wiki:Map
  • 此示例使用-c:v copy将视频进行stream copy(mux)。视频不会重新编码,质量得以保留,处理速度快。
    • 如果您的输入音频格式与输出格式兼容,则将-c:v copy更改为-c copy以流式复制视频和音频
    • 如果要重新编码视频和音频,则删除-c:v copy / -c copy
  • -shortest选项将使输出与最短输入持续时间相同。

将两个音频输入混合/组合成一个

diagram of audio downmix

使用来自video.mkv的视频。使用amerge filter混合来自video.mkvaudio.m4a的音频:
ffmpeg -i video.mkv -i audio.m4a -filter_complex "[0:a][1:a]amerge=inputs=2[a]" -map 0:v -map "[a]" -c:v copy -ac 2 -shortest output.mkv

查看FFmpeg Wiki:音频通道以获取更多信息。

生成无声音频

您可以使用anullsrc过滤器生成无声音频流。该过滤器允许您选择所需的通道布局(单声道、立体声、5.1等)和采样率。

ffmpeg -i video.mp4 -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
-c:v copy -shortest output.mp4

还可以参考


8
一开始这个方法对我没用,但是改用“-map 0:0 -map 1:0”而不是“-map 0 -map 1”就成功了。谢谢! - yonix
添加静音音频流的选项非常棒!我试图通过Telegram发送一个静音视频,并希望将其显示为视频而不是gif(Telegram gui将短静音视频显示为gif);添加一个空的音频流欺骗了Telegram! - Javier Mr
我正在尝试将两个音频输入混合/合并成一个的命令。 - 1234567
如果你遇到了“Timestamps are unset in a packet for stream 0.”的警告,你可以尝试在第一个“-i”之前添加“-fflags +genpts”。https://trac.ffmpeg.org/ticket/7434 - Hang Chen
1
这份文档帮助我理解-map以更好地满足我的需求 - https://trac.ffmpeg.org/wiki/Map - Hang Chen
显示剩余14条评论

31

将MP3音乐转换为WAV格式

ffmpeg -i music.mp3 music.wav

截断以适应视频

ffmpeg -i music.wav -ss 0 -t 37 musicshort.wav

混合音乐和视频
ffmpeg -i musicshort.wav -i movie.avi final_video.avi

4
据我记忆,最新版本将使用新音频替换旧音频。 - Vetalll
有没有选项可以将新音频与旧音频合并? - Iqbal Malik
1
@jwilson 我尝试了这个命令,但是我失去了视频音频。我的视频格式是mp4。 - Allan
@Allan的解决方案是什么,以免丢失? - Kiquenet

28

如果输入视频有多个音轨,且您需要添加一个音轨,则使用以下命令:

ffmpeg -i input_video_with_audio.avi -i new_audio.ac3 -map 0 -map 1 -codec copy output_video.avi

-map 0表示从第一个输入文件(input_video_with_audio.avi)复制(包括)所有流,-map 1表示包括第二个输入文件(new_audio.ac3)中的所有流(在本例中为一个流)。


我认为,这个答案一定是最好的答案。 - Nabi K.A.Z.

7

对我来说,这些解决方案都不太适用。我的原始音频要么被覆盖了,要么使用更复杂的“amerge”示例时会出现“无法映射内存”的错误。看来我需要使用“-filter_complex amix”。

ffmpeg -i videowithaudioyouwanttokeep.mp4 -i audiotooverlay.mp3 -vcodec copy -filter_complex amix -map 0:v -map 0:a -map 1:a -shortest -b:a 144k out.mkv

5

我尝试了很多方法,但都没有成功(我认为是因为我的输入.mp4视频没有任何音频),所以我发现这个方法适用于我:

ffmpeg -i input_video.mp4 -i balipraiavid.wav -map 0:v:0 -map 1:a:0 output.mp4


这会重新编码所有内容吗? - Michael

1

以下是我实现OP所需的方法。

我的设置是有两个媒体流,一个视频(带有自己的音频通道)和一个音频。我没有进行转换,而是通过将其与额外的音频通道集成来重新流式传输实时源,而无需替换视频流中的旧音频。

以下是我使用的代码。

ffmpeg -i "Video stream with its own audio" -i "another audio stream" -map 0:v -map 0:a -map 1:a -shortest -f mpegts "multicast udp stream out put"

代码的作用是,从直播源获取流后,将每个视频和音频通道映射。 -map 0:v 是视频流,-map 0:a 是来自视频源的音频(请注意来自 -map 的 0),最后是 -map 1:a,这是第二个源的音频流。
然后,它只需通过多播地址使用 mpegts 重新流传。您可以将其更改为文件、单播流或任何其他支持的输出格式。
这是我正在使用的代码。
ffmpeg -i "rtp://@231.0.0.208:1234" -i "rtp://@231.0.0.206:1234" -map 0:v -map 0:a -map 1:a -shortest -f mpegts "udp://@231.0.0.45:1234"

希望这能帮助到某些人。谢谢!

1
这里展示了如何使用ffmpeg将所有音频轨道合并到一个整个目录中:
ffmpeg -i video.mp4 -i audio.mp3 -map 0:v -map 1:a -c:v copy -shortest output.mp4

0

如果你正在使用旧版本的FFMPEG,而且不能升级,那么可以尝试以下措施:

ffmpeg -i PATH/VIDEO_FILE_NAME.mp4 -i PATH/AUDIO_FILE_NAME.mp3 -vcodec copy -shortest DESTINATION_PATH/NEW_VIDEO_FILE_NAME.mp4

注意我使用了-vcodec

0

被标记的答案没有设置音轨语言。

以下是一个示例,它将默认音轨(视频的唯一音频通道)设置为德语,并将新增的音轨设置为英语:

ffmpeg -i "/dir/video.mkv" -i "/dir2/audio.ac3" -map 0 -map 1:a -c:v copy -shortest -metadata:s:a:0 language=ger -metadata:s:a:0 title="GER" -metadata:s:a:1 language=eng -metadata:s:a:1 title="ENG" "/dir/output.mkv"

s:a:0从0开始计数,根据需要进行调整。如果音轨语言已经指定,则不需要设置,只需要为您添加的音轨设置即可。)


-1

使用ffmpeg添加音频到视频的代码。

如果音频长度大于视频长度,它将剪切音频以匹配视频长度。 如果您想在视频中保留完整的音频,请从cmd中删除-shortest。

String[] cmd = new String[]{"-i", selectedVideoPath,"-i",audiopath,"-map","1:a","-map","0:v","-codec","copy", ,outputFile.getPath()};

private void execFFmpegBinaryShortest(final String[] command) {



            final File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/videoaudiomerger/"+"Vid"+"output"+i1+".mp4");




            String[] cmd = new String[]{"-i", selectedVideoPath,"-i",audiopath,"-map","1:a","-map","0:v","-codec","copy","-shortest",outputFile.getPath()};


            try {

                ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
                    @Override
                    public void onFailure(String s) {
                        System.out.println("on failure----"+s);
                    }

                    @Override
                    public void onSuccess(String s) {
                        System.out.println("on success-----"+s);
                    }

                    @Override
                    public void onProgress(String s) {
                        //Log.d(TAG, "Started command : ffmpeg "+command);
                        System.out.println("Started---"+s);

                    }

                    @Override
                    public void onStart() {


                        //Log.d(TAG, "Started command : ffmpeg " + command);
                        System.out.println("Start----");

                    }

                    @Override
                    public void onFinish() {
                        System.out.println("Finish-----");


                    }
                });
            } catch (FFmpegCommandAlreadyRunningException e) {
                // do nothing for now
                System.out.println("exceptio :::"+e.getMessage());
            }


        }

1
Environment.getExternalStorageDirectory().getAbsolutePath()+"/videoaudiomerger/"+"Vid"+"output"+i1+".mp4" 是什么? - Kiquenet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接