我正在尝试使用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文件合并在一起并使其正常工作。


当前回答

这里有一种快速(不到1分钟)且无损的方法,无需中间文件即可完成此操作:

ls Movie_Part_1.mp4 Movie_Part_2.mp4 | \
perl -ne 'print "file $_"' | \
ffmpeg -f concat -i - -c copy Movie_Joined.mp4

“ls”包含要加入的文件“perl”在管道中动态创建连接文件“-i-”部分告诉ffmpeg从管道读取

(注意——我的文件中没有空格或奇怪的东西——如果你想用“硬”文件实现这个想法,你需要适当的shell转义)。

其他回答

对于Windows Powershell

创建文件列表

PS > ls file* | % { $n = $_.name; "file '\$n'" } | out-file mylist.txt

检查创建的文件

PS > cat mylist.txt
file '/path/to/file1.mkv'
file '/path/to/file2.mkv'
file '/path/to/file3.mkv'

运行ffmpeg(不要忘记列表文件的attach./)

PS > ffmpeg -safe 0 -f concat -i ./mylist.txt -c copy file.mkv
ffmpeg version git-2020-05-15-b18fd2b Copyright (c) 2000-2020 the FFmpeg developers
...

这是我使用命令替换和concat视频过滤器(这将重新编码)来加入一个满是MP4文件的目录的方法-我认为其他人会从这一行代码中得到一些用处,特别是如果你有很多文件(我刚刚一下子加入了17个文件):

ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4

注意:此命令按照文件的命名顺序(即,如果运行ls*.mp4,则与文件的显示顺序相同)连接文件-在我的情况下,它们都有一个曲目号,因此效果很好。

经过多次尝试后,以下脚本在windows 10 powershell上对我有效。

    $files=Get-ChildItem -path e:\ -Filter *.mp4


    $files| ForEach-Object  {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII


    if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}

    E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4

    # Conversion Cleanup
    Remove-Item e:\temp.txt

这里,前两行创建一个文本文件temp.txt,其中包含以下内容

file 'e:\first.mp4'
file 'e:\second.mp4'

第三、第四行检查ffmpeg在路径上是否可用,并创建“joind.mp4”

与其他答案的主要区别如下

usage  of -bsf:v hevc_mp4toannexb -an

对于我上面的mp4文件,您可能需要根据您的视频编码使用以下其他选项。

h264_mp4toannexb

所有这些可能的比特流过滤器都可以在https://ffmpeg.org/ffmpeg-bitstream-filters.html

对于那些需要连接许多用H.264编码的MP4视频的人,我提出了一个Python脚本mp4concat.py,它可以自动执行Concat协议/使用ffmpeg文档中的中间文件段落。

从上面的链接或使用

wget https://gist.githubusercontent.com/mwouts/115956d3fc7ece55cbce483a7a5148bd/raw/4bc5e03952f1b981dac3f97f4daf82c907774b17/mp4concat.py

然后将其用作

python3 mp4concat.py input1.mp4 ... inputN.mp4 --output output.mp4

这里是我制作的一个脚本,将几个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}