在 linux 中加入 mp4 文件

Jos*_*ndo 41 mp4 join concatenation

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

MP4Box -add video1.mp4 -cat video2.mp4 newvideo.mp4
Run Code Online (Sandbox Code Playgroud)

不幸的是,音频变得混乱了。我认为问题是音频在 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
Run Code Online (Sandbox Code Playgroud)

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

evi*_*oup 47

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

file '/path/to/input1.mp4'
file '/path/to/input2.mp4'
file '/path/to/input3.mp4'
Run Code Online (Sandbox Code Playgroud)

然后,只需运行此 ffmpeg 命令:

ffmpeg -f concat -i inputs.txt -c copy output.mp4
Run Code Online (Sandbox Code Playgroud)

另请参阅FAQ 中的串联ffmpeg


为了任何使用旧版本 ffmpeg 的人的利益,我在此保留以下内容。

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

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts
Run Code Online (Sandbox Code Playgroud)

如果这引发了关于 h264的错误 [ 1 ],您可能需要使用:

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf:v h264_mp4toannexb middle.ts
Run Code Online (Sandbox Code Playgroud)

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

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy output.mp4
Run Code Online (Sandbox Code Playgroud)

如果这引发了关于 aac 的错误,您可能需要使用

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy -absf aac_adtstoasc output.mp4
Run Code Online (Sandbox Code Playgroud)

如果您的系统支持命名管道,则无需创建中间文件即可执行此操作。

mkfifo temp0 temp1
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

如果您的输入文件不同,这可能不起作用 - 我相信比特率的差异是可以的,但帧大小、帧速率等必须匹配。

  • @DaveJarvis 不是这样;这是由 libav 团队故意和恶意传播的消息,他们是一群从 ffmpeg 项目中分离出来开发 avconv 的开发人员(并更改了名称,因为他们无法保护 ffmpeg 名称的版权)。参见【谁能告诉我ffmpeg、libav、avconv的区别和关系?】(http://stackoverflow.com/questions/9477115/who-can-tell-me-the-difference-and-relation-between- ffmpeg-libav-and-avconv)了解更多信息。 (2认同)
  • `*** 此程序已弃用 *** 此程序仅用于兼容性目的,将在未来版本中删除。请改用 avconv。` 是我现在在运行 `ffmpeg` 时看到的消息 (2认同)

Phi*_*oud 8

对于 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
Run Code Online (Sandbox Code Playgroud)

或命令是

MP4Box -cat file1.mp4 -cat file2.mp4 -new mergedFile.mp4
Run Code Online (Sandbox Code Playgroud)

使用 mencoder 和 avconv 我无法让它工作:-(


小智 5

这是一个单线,使这一切变得更加容易。它会完成所有需要做的事情,以便最终为您提供一个生成的视频文件。干杯!

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