如何在Ubuntu上合并多个(两个以上)视频?


38

我想合并批量为二十(20)个的视频。我正在运行Linux计算机。这些视频为mp4格式,质量中等。有些甚至没有音频流。到目前为止,我已经试过ffmpegmencodercvlc/vlcMP4Box。由于要进行批处理,因此我想编写一个命令行脚本来实现此目的。

主要问题是,我尝试过的某些解决方案对两个视频都适用,某些解决方案对具有音频流的视频也适用,而另一些解决方案对我的视频集的其他子集也适用。但是,我无法找到针对此任务的全面解决方案。


2
请不要在多SE网站问同样的问题superuser.com/questions/928548/...
Maythux

您能否具体介绍到目前为止的尝试?
ohaal 2015年

1
@ohaal我尝试使用中提供的各种串联方法ffmpeg,包括过滤器和文件协议。我也尝试使用的concat功能cvlc/vlc。我还尝试了的concat功能mencoder。所有这些都部分起作用。终于帮助我解决了这个问题。
Dhruv Singal

是的,您已经提到了这些工具,我的意思是您运行的实际命令。如果您可以包括最终为您(在您的答案中)为将来的访问者解决该命令的命令,那也很好。
ohaal

啊,我明白你的意思。不幸的是,由于数量过多,我无法列出命令。解决我问题的命令是melt {input-sequence} -consumer avformat:{output-name} acodec=libmp3lame vcodec=libx264
Dhruv Singal

Answers:


41

mkvmerge用来将多个MP4文件合并为一个文件:

mkvmerge -o outfile.mkv infile_01.mp4 \+ infile_02.mp4 \+ infile_03.mp4

3
最好将扩展名.mkv用于输出文件,因为无论您提供什么扩展名,它都是Matroska容器。
haridsv

安装方法mkvmerge如下:tipsonubuntu.com
Morgoth

仅此命令mkvmerge有效。所有ffmpeg的音频至少都会因音频移位而失败。
22n4

25

您可以使用ffmpeg

ffmpeg -i concat:"input1.mp4|input2.mp4" output.mp4

参考和更多信息


2
我尝试这样做。问题在于它没有给出正确的答案。1.音频轨道混乱。2.视频轨道中有些干扰。
Dhruv Singal

我使用它的目的不只是样本,其结果是高质量,也许您的源视频质量是问题?
Maythux 2015年

你可能是对的。这就解决了问题:askubuntu.com/a/637179/420614
Dhruv Singal

2
不要使用concat协议来串联MP4。它仅适用于大多数普通用户不会遇到的某些格式。改用concat解复用器或concat过滤器
llogan

我尝试了ffmpeg,每个文件有30分钟的2个mp4文件。我得到了一个长度为7小时的输出文件。
Guus


4

我编写了一个小外壳脚本来连接MP4,而无需使用ffmpeg进行转码。

for f in $(ls *.MP4); do
    ffmpeg -i $f -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts
done

CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g")

ffmpeg -i "concat:$CONCAT" -c copy -bsf:a aac_adtstoasc output.mp4

rm *.ts

这将在MPEG容器中创建中间文件,然后将它们连接成MP4。


重要的是要注意,如果任何文件名包含空格或在某些情况下包含特殊字符,此脚本将失败。对于循环,最好for f in *.MP4不使用ls。(ls出于两个重要原因,您应始终避免在脚本中使用脚本;有更好的选择。)此外,对变量使用引号,除非您确定没有空格或其他特殊字符,所以"${f}"(或只是"$f")而不是未加引号$f
帕迪·兰道

CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g")不适用于文件名为1、2、3 ... 10 ... 20的文件。它最终将它们解析为1、10 ... 2、20 ...等。我建议CONCAT=$(echo $(ls -v *.ts) | sed -e "s/ /|/g")这样做可以确保顺序。
tisaconundrum

2

用以下形式创建要连接的所有文件的文件files.txt(以#开头的行将被忽略):

# this is a comment
file 'file1.mp4'
file '/path/to/file2.mp4'
file 'file3.mp4'

请注意,这些路径可以是相对路径,也可以是绝对路径。然后,您可以流式复制或重新编码文件:

ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

0

我的脚本,完全在bash和中ffmpeg。将命令行中提供的文件重新编码为一个。

要求文件具有相同的分辨率。接受不同的元数据旋转,ffmpeg concat:但不是。

rm ffmpeg-concat-output.mkv

FILE_COUNT=$#
INPUTS=""
FILTER=""
INDEX=0
for FNAME in $@; do
    echo "Processing ${FNAME}"
    INPUTS="${INPUTS} -i $FNAME"

    if [ -z "${FILTER}" ]; then
        FILTER="[$INDEX:v:0] [$INDEX:a:0]"
    else
        FILTER="${FILTER} [$INDEX:v:0] [$INDEX:a:0]"
    fi
    let INDEX+=1
done

COMMAND="ffmpeg ${INPUTS} \
    -filter_complex '${FILTER} \
        concat=n=${INDEX}:v=1:a=1 [v] [a]' \
    -map '[v]' -map '[a]' \
    ffmpeg-concat-output.mkv"

#   -af 'volume=15dB' # won't work with -filter_complex

bash -c "${COMMAND}"

0

我创建了一个Python脚本,该脚本使用moviepy可以串联子段(例如,如果您想从视频中删除某些部分,则很有用)。

搭配使用:

vcat -i inputfile1,inputfile2[start-end],... -o <outputfile>

-1

除了Maythux的答案,还来自

一些多媒体容器(MPEG-1,MPEG-2 PS,DV)仅通过串联包含它们的文件就可以将视频串联起来。

也就是说,要连接的视频使用上述视频容器之一(我将在其中添加MPEG-4 Part 14以供个人使用),您可以简单地:

cat video1.ext video2.ext video3.ext > video4.ext

1
我试过了,但它只返回第一个视频作为输出。我在某处读到它行不通,尽管我不记得背后的理由。
Dhruv Singal

@DhruvSingal是的,我可以确认这一点,我已经在两个具有完全相同的视频/音频编码的MP4视频上进行了尝试,因为您只能浏览第一个视频。这似乎是合理的,但是我很确定我之前已经通过几个MP4视频做到了这一点。可能内存在这里不能很好地工作,或者有其他要求才能使它工作。我也想对此进行研究,如果我有兴趣的话,我会更新答案并给您留言
kos 2015年

我们需要以某种方式在第一个视频的开头更改元数据,以涵盖组合电影的整个长度,以及可能包含的其他内容。只有少数的MPEG4文件让我看到了元数据..
肯Mollerup
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.