ffmpeg批处理合并视频,不需要渲染

剪辑笔记

作者: shisaq 日期: April 14, 2022

合并2个视频(需要渲染)

参考:FFmpeg split video and merge back

假设1.mp4需要所有片段,2.mp4需要3秒之后的片段,并保留两者音频,则可用如下代码。但该方法需要重新渲染

  • [0:v]指第1个input的视频
  • [0:a]指第1个input的音频
  • [v0]指把这一行保存为[v0]
  • [v0][a0][v1][a1]表示导出的顺序
  • concat=n=2表示合并的视频有2段
  • :v=1:a=1表示音频视频都要导出
  • -map "[outv]"表示重新定义[outv]的时间戳
1
2
3
4
5
6
7
$ ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "\
[0:v]trim=start=0,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=start=0,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=start=3,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=start=3,asetpts=PTS-STARTPTS[a1]; \
[v0][a0][v1][a1]concat=n=2:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

删除前3秒

参考资料:Cut part from video file from start position to end position with FFmpeg

1
$ ffmpeg -ss [start] -i in.mp4 -t [duration] -c copy out.mp4

如果仅需要把1.mp4的前3秒删除,剩下的部分保存到output.mp4,则可以省略-t [duration]

1
$ ffmpeg -ss 3 -i 1.mp4 -c copy output.mp4

合并2个视频(不需要渲染)

参考资料:How to Merge two videos without re-encoding

必须确保2个视频的编码、尺寸、fps等基本设置都一致,才能正确合并!

1
ffmpeg -f concat -fase 0 -i list.txt -c copy output.mp4

list.txt需要在当前文件夹下,内容格式如下:

file '1.mp4'
file '2.mp4'

用Python批处理当前文件夹下需要合并的文件

假设每2个文件都需要合并,文件命名为1.mp41-intro.mp4,则需要先为每批文件制作1个txt文件:

1
2
3
4
5
6
7
8
9
# -*- coding: utf-8 -*-
import os

files = [f for f in os.listdir('.') if os.path.isfile(f)]
for f in files:
    if (f.endswith(".mp4"):
        with open("%s.txt" % f, "w") as file:
            intro = f.rsplit('.', 1)[0]
            file.write("file '%s-intro.mp4'\nfile '%s'" % (intro,f))

结果将产生1.mp4.txt文件,内容为:

file '1-intro.mp4'
file '1.mp4'

现在,我们就可以把1-intro.mp41.mp4通过1.mp4.txt合并成1个文件了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-
import os
import subprocess

files = [f for f in os.listdir('.') if os.path.isfile(f)]

for f in files:
    if (f.endswith(".mp4") and "intro" not in f):
        filename = f.rsplit('.', 1)[0]
        cmd = "ffmpeg -f concat -safe 0 -i '%s.txt' -c copy '%s-final.mp4'" % (f, filename)
        print(cmd)
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        p.wait()
    else:
        continue

生成的文件为1-final.mp4,以及其他以同样格式命名的文件组。