在Linux中加入mp4文件


31

我想加入两个mp4文件来创建一个。视频流以h264编码,音频以aac编码。由于计算原因,我无法将视频重新编码为其他格式。另外,我不能使用任何GUI程序,必须使用Linux命令行实用程序执行所有处理。FFmpeg无法对mpeg4文件执行此操作,因此我改用了MP4Box:

MP4Box -add video1.mp4 -cat video2.mp4 newvideo.mp4

不幸的是,音频混在一起了。我以为问题是音频在aac中,所以我在mp3中对其进行了转码并再次使用了MP4Box。在这种情况下,音频的前半部分newvideo.mp4(对应video1.mp4)可以正常播放,但是它们没有音频,因此我也无法在视频中导航。

我的下一个想法是,音频和视频流的长度有些细微的差异,我应该修复。因此,对于每个输入视频,我都会拆分视频和音频流,然后使用FFmpeg中的-shortest选项将它们加入。

因此,对于第一个视频,我运行了:

 avconv -y -i video1.mp4 -c copy -map 0:0 videostream1.mp4
 avconv -y -i video1.mp4 -c copy -map 0:1 audiostream1.m4a
 avconv -y -i videostream1.mp4 -i audiostream1.m4a  -c copy -shortest  video1_aligned.mp4

类似地,对于第二个视频,然后像以前一样使用MP4Box。不幸的是,这也不起作用。我唯一的成功是当我分别加入视频流(即videostream1.mp4和videostream2.mp4)和音频流(即audiostream1.m4a和audiostream2.m4a),然后将视频和音频加入最终文件时。但是,视频的后半部分失去同步。具体而言,音频和视频会有1秒的延迟。任何建议都非常欢迎。


“ FFmpeg无法对mpeg4文件执行此操作,因此我使用了MP4Box”您是指MP4文件吗?两个音频视频流都使用相同的编码参数(宽度,高度,SPS,PPS,帧率,采样率,通道数吗?)

使用ffprobe,我看到音频流具有相同的属性。视频流具有相同的尺寸,但速率不同。对于第一个视频:h264,720x592,277 kb / s,PAR 18944:12915 DAR 512:287,24.97 fps,45k tbr,90k tbn,90k tbc,而对于第二个视频:h264,720x592,226 kb / s, PAR 481:330 DAR 39:22,24.91 fps,45k tbr,90k tbn,90k tbc。您是否认为这是我的问题的根源?

MP4支持使用不同的轨道为不同的视频加入具有不同特征的视频/音频,但是播放器并不那么聪明。
rajneesh


ffmpeg常见问题解答已经回答了您的问题:ffmpeg.org/faq.html#How-can-I-join-video-files_003f
Palec 2013年

Answers:


31

目前最好的方法是使用concat demuxer。首先,创建一个名为inputs.txtformat 的文件,如下所示:

file '/path/to/input1.mp4'
file '/path/to/input2.mp4'
file '/path/to/input3.mp4'

然后,只需运行以下ffmpeg命令:

ffmpeg -f concat -i inputs.txt -c copy output.mp4

另请参阅FAQ中的串联ffmpeg


我在此保留以下内容,以使使用旧版本ffmpeg的用户受益。

最新版本的ffmpeg可以做到这一点:您必须首先将文件重新混合到mpeg传输流中(相当轻巧,因为它只是更改了容器格式):

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

如果那引发关于h264的错误,则您可能需要使用:

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

您必须分别对每个输入文件执行此操作。要将文件串联在一起,请使用:

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy output.mp4

如果这样会引发关于AAC的错误,则可能需要使用

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy -absf aac_adtstoasc output.mp4

如果系统支持命名管道,则可以在不创建中间文件的情况下执行此操作。

mkfifo temp0 temp1

您必须在三个独立的虚拟终端中执行以下操作:

ffmpeg -i input0.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp0
ffmpeg -i input1.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp1
ffmpeg -f mpegts -i "concat:temp0|temp1" -c copy -absf aac_adtstoasc output.mp4

如果output.mp4已经存在,则第三个ffmpeg将询问您是否要覆盖它,但是它将在访问FIFO后执行此操作,这将使第一个ffmpegs关闭。因此,请确保为输出文件选择一个未使用的名称。

如果您的输入文件不同,这可能无法正常工作-我相信位速率的差异可以,但是帧大小,帧速率等必须匹配。


许多伴侣,像魅力一样工作
Jose Armando

2
@DaveJarvis不是这样;这是libav团队故意和恶意传播的消息,他们是一群从ffmpeg项目拆分而来开发avconv的开发人员(并更改了名称,因为他们无法获得ffmpeg名称的版权)。参见谁能告诉我ffmpeg,libav和avconv之间的区别和关系?有关更多信息。
evilsoup

2
*** THIS PROGRAM IS DEPRECATED *** This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.是我现在看到的跑步信息ffmpeg
卢勋爵。

@LordLoh。请参阅我之前的评论中的链接。
evilsoup 2014年

1
这个答案不能回答-如何将mp4与avconv
Lord Loh连接。

7

对于mp4,我发现的唯一有效解决方案是使用gpac包中的MP4Box

#!/bin/bash
filesList=""
for file in $(ls *.mp4|sort -n);do
    filesList="$filesList -cat $file"
done
MP4Box $filesList -new merged_files_$(date +%Y%m%d_%H%M%S).mp4

或命令是

MP4Box -cat file1.mp4 -cat file2.mp4 -new mergedFile.mp4

与mencoder和avconv我不能使其工作:-(


2

感谢您的脚本dvo。对我来说,这是一个很好的起点。我使用命名管道没有问题,因此我改编了脚本以使用它们。另外,我修复了它以使用文件名中包含空格的问题。在开始读取命名管道之前,输出不会“运行”,因此需要在最终调用avconv之前使用&为初始remux任务设置背景。另外,不要忘了使用-c复制,否则最终将对整个文件进行重新编码。

#!/bin/bash
for FILE in "$@"; do
   TAG=$(echo "$FILE" | sed -e s/[^A-Za-z0-9.]/_/g)
   mkfifo $TAG.mp4concatpipe
   avconv -loglevel "quiet" -i "$FILE"  -f mpegts -c copy -bsf h264_mp4toannexb -y $TAG.mp4concatpipe &
   IN=$IN\|$TAG.fifo
done

IN=${IN#\|}
avconv -i concat:$IN -c copy out.mp4
rm *.mp4concatpipe

由于某种原因,这给了我一个“ concat:first.m4v.fifo | second.m4v.fifo:没有这样的文件或目录”的错误。 $ IN”)。以下其他答案中建议的MP4Box效果很好!
vorburger 2014年

2

在Mac(macOS 10.13 High Sierra)上,我成功使用了以下命令:

for f in *.m4a; do echo "file '$f'" >> mylist.txt; done

如有必要,请按上述类似方式重新排序(请注意,。/已删除-路径导致ffmpeg抛出不安全的文件名错误)。

然后,我必须删除为默认MacPorts ffmpeg指定的编解码器和比特率,以使其喜欢:

ffmpeg -f concat -i mylist.txt  output.m4a

欢迎使用超级用户!,请仔细阅读问题。您的答案没有回答关于linux的原始问题。如果您相信它可以在linux上运行,请补充一点,以便将来的读者有一个清晰的了解,除此之外,再次欢迎超级用户,并感谢您的输入。请花几分钟的时间,并宣读: - superuser.com/help .Answering:superuser.com/help/how-to-answer
mic84 '17

2

这是一个单行代码,它使这一切变得更加容易。它会完成所有必要的工作,以便最终为您提供一个生成的视频文件。干杯!

find *.mp4 | sed 's:\ :\\\ :g'| sed 's/^/file /' > list.txt; ffmpeg -f concat -i list.txt -c copy output.mp4; rm list.txts

1

谢谢罪恶汤;这是一个使用更新的脚本来自动化该过程avconv
顺便说一句,命名管道对我不起作用(它们的输出卡住了)。

   #!/bin/bash

    for FILE in $@; do
      avconv -i $FILE -map 0 -f mpegts -bsf h264_mp4toannexb -c:v copy -y $FILE.tmp
      IN=$IN\|$FILE.tmp
    done

    IN=${IN#\|}
    avconv -i concat:"$IN" out.mp4

    for FILE in $@; do
      rm $FILE.tmp
    done

0

取得了巨大的成功

for f in ./*.m4a; do echo "file '$f'" >> mylist.txt; done

您可能需要稍微重新排序mylist.txt

ffmpeg -f concat -i mylist.txt -c:a libfdk_aac -b:a 128k output.m4a

ffmpeg版本2.2.3

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.