我正在尝试使用ffmpeg连接两个mp4文件。我需要这是一个自动过程,因此我选择了ffmpeg。我将这两个文件转换为.ts文件,然后将它们连接起来,然后尝试对连接的.ts文件进行编码。文件是h264和aac编码的,我希望保持质量相同或尽可能接近原始。

ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

不幸的是,我在编码过程中从ffmpeg返回以下错误消息:

[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s    
av_interleaved_write_frame(): Error while opening file

这种情况大约发生在编码的一半,这让我认为不能将两个.ts文件合并在一起并使其正常工作。


当前回答

这里是我制作的一个脚本,将几个GoPro mp4连接成720p mp4。希望能有所帮助。

#!/bin/sh
cmd="( "
for i; do
    cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}

其他回答

我有不同编码器libx264和H.264的剪辑

我将所有剪辑转换为libx264,并使用了来自最高投票答案的解复用器方法。

ffmpeg -i input.flv -vcodec libx264 output.mp4

根据rogerdpack和Ed999的回答,我创建了.sh版本

#!/bin/bash

[ -e list.txt ] && rm list.txt
for f in *.mp4
do
   echo "file $f" >> list.txt
done

ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt

它将当前文件夹中的所有*.mp4文件连接到joined-out.mp4中

在mac上测试。

得到的文件大小正好是我测试的60个文件的总和。应该不会有任何损失。正是我需要的

主要答案不适用于我,因为它给了我下面在“疑难解答”部分描述的错误,所以这里是我自己的答案。

如何使用ffmpeg连接或组合许多mp4视频文件

快速摘要

创建一个inputs.txt文件,其中包含要合并的所有文件路径的列表(请参见下面的示例)。然后,将以上所有视频组合成一个这样的视频:

# Option 1 (preferred): into a single mp4 video with AAC audio encoding
# and original video encoding
time ffmpeg -f concat -safe 0 -i inputs.txt -c:v copy -c:a aac output.mp4

# Option 2: into a single .mkv video with original audio and video encoding
time ffmpeg -f concat -safe 0 -i inputs.txt -c copy output.mkv

结合威泽安全摄像机镜头的细节和完整示例

在Ubuntu 20.04上进行了测试,将我的一系列Wyze安全摄像头视频合并为一个视频。(我将相机的微型SD卡直接插入电脑)。

创建一个名为inputs.txt的文件,其中包含要连接的所有文件的列表。前任:文件“path/to/file1.mp4”文件“path/to/file2.mp4”文件“path/to/file3.mp4”在我的案例中,我将2022年11月13日18:31(下午6:31)至2022年12月13日19:39(下午7:39)的69分钟视频合并在一起。在怀泽安全摄像头路径中,这意味着从记录/2021113/18/31.mp4’到记录/2021111/19/39.mp4,包括在内。下面是我的完整inputs.txt文件:文件'/media/ggabriel/3339-3730/record/20221113/18/31.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/32.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/33.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/34.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/35.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/36.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/37.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/38.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/39.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/40.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/41.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/42.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/43.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/44.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/45.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/46.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/47.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/48.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/49.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/50.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/51.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/52.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/53.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/54.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/55.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/56.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/57.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/58.mp4'文件'/media/ggabriel/3339-3730/record/20221113/18/59.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/00.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/01.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/02.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/03.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/04.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/05.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/06.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/07.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/08.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/09.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/10.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/11.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/12.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/13.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/14.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/15.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/16.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/17.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/18.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/19.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/20/mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/21.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/22.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/23.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/24.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/25.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/26.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/27.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/28.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/29.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/30.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/31.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/32.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/33.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/34.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/35.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/36.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/37.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/38.mp4'文件'/media/ggabriel/3339-3730/record/20221113/19/39.mp4'将以上所有视频合并为一个:#选项1(首选):使用AAC音频编码将mp4视频转换为单个mp4视频#和原始视频编码时间ffmpeg-f concat-safe 0-i inputs.txt-c:v copy-c:aac输出.mp4#选项2:将原始音频和视频编码转换为单个.mkv视频时间ffmpeg-f concat-safe 0-i inputs.txt-c copy output.mkv

在我的例子中,最初的69个文件占用了411.1MB。下面是上面两个命令的结果:

output.mp4的制作耗时11秒,大小为380.3 MB。AAC编码的音频显然有点小。output.mkv的制作耗时8秒,大小为410.7MB。

故障排除/可能的错误

如果运行ffmpeg-f concat-i inputs.txt-c copy output.mp4并得到以下错误:[cont@0x563ca0173700]不安全的文件名'/media/gabriel/3339-370/record/2021113/18/31.mp4'inputs.txt:不允许操作……这是因为你忘了使用-safe 0。参见:https://nono.ma/says/concat-unsafe-file-name-operation-not-permittedffmpeg concat:“不安全的文件名”如果运行ffmpeg-f concat-safe 0-i inputs.txt-c copy output.mp4并得到以下错误:[mp4@0x55ced96f2100]在流#1中找不到编解码器pcm_law的标记,容器中当前不支持编解码器无法写入输出文件#0的标头(编解码器参数不正确?):参数无效…这是因为“ffmpeg不支持MP4容器中的PCM(PCM_law、PCM_s16le等)。”请参阅此处:容器和此处当前不支持编解码器。因此,请运行ffmpeg-f concat-safe 0-i inputs.txt-c:v copy-c:aaac output.mp4,将音频重新编码为aac格式。或者,运行时ffmpeg-f concat-safe 0-i inputs.txt-c copy output.mkv将其写入.mkv容器,而不是.mp4容器。

这里有一个脚本(适用于任意数量的指定文件(不仅仅是工作目录中的所有文件),没有附加文件,也适用于.mov;在macOS上测试):

#!/bin/bash

if [ $# -lt 1 ]; then
    echo "Usage: `basename $0` input_1.mp4 input_2.mp4 ... output.mp4"
    exit 0
fi

ARGS=("$@") # determine all arguments
output=${ARGS[${#ARGS[@]}-1]} # get the last argument (output file)
unset ARGS[${#ARGS[@]}-1] # drop it from the array
(for f in "${ARGS[@]}"; do echo "file '$f'"; done) | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy $output

FFmpeg有三种连接方法:

1.凹面视频过滤器

如果您的输入没有相同的参数(宽度、高度等),或者格式/编解码器不相同,或者您想要执行任何过滤,请使用此方法。

注意,该方法对所有输入执行重新编码。如果要避免重新编码,可以只对不匹配的输入进行重新编码,以便它们共享相同的编解码器和其他参数,然后使用concat解复用器避免对所有内容进行重新编码。

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
-filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] \
concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mkv

2.凹面分离器

如果您希望避免重新编码,并且您的格式不支持文件级连接(一般用户使用的大多数文件不支持文件级别连接),请使用此方法。

$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
    
$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

对于Windows:

(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

3.concat协议

将此方法用于支持文件级连接的格式(MPEG-1、MPEG-2ps、DV)。不要与MP4一起使用。

ffmpeg -i "concat:input1|input2" -codec copy output.mkv

该方法不适用于许多格式,包括MP4,因为这些格式的性质以及该方法执行的简单连接。


如果对使用哪种方法有疑问,请尝试concat解复用器。

另请参见

FFmpeg常见问题解答:如何加入视频文件?FFmpeg Wiki:如何连接(连接、合并)媒体文件