我正在尝试使用 FFmpeg 根据一些输入分割视频start_time
,end_time
并将其替换为其他视频文件。例如,对于输入,10 15
我需要将 EXACT 秒替换10 to 15
为另一个视频。
好的。我想到的是:
- 首先分割视频(在本例中为 0-10、10-15 和 15-结束)
- 用另一个视频替换10-15
- 将所有子视频合并回来
第一个问题:这是最好和最快的解决方案吗?我们是否有更简单的命令或其他工具可以用另一个视频替换视频中的特定时间段?
第二个问题:假设 FFmpeg 是可行的解决方案,当我简单地使用命令时ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4
,我的视频处理代码无法读取和处理文件。我使用mediainfo
工具比较了这两个文件,发现标头大小存在差异,而所有与视频编解码器相关的内容都相同。我注意到 HEADER SIZE 不同,这显然导致了问题。有没有办法强制标头大小(编解码器除外)也相同?
更新:这是原始.mp4
文件在模拟器中运行良好。
答案1
使用trim
和concat
– 具有不同编解码器的源文件
为此,请确保您的各个文件具有相同的分辨率,并且最好具有相同的帧速率和色度子采样等。这将防止连接期间出现错误或故障。
你可以一次性完成所有操作,无需拆分文件,使用trim
和concat
过滤器:
ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4
此处,trim
用于指定您稍后想要连接的输入视频流( 0:v
、 )的各个部分。这些部分通过命名。(过滤器将这些各个部分的时间戳重置为 0,这是连接所必需的)。稍后,我们将这三个部分连接起来。1:v
v0
v2
setpts
如果要从某个时间戳修剪到末尾,请使用trim=start=15
而不是指定范围。
如果您的文件有音频,您必须分别修剪这些流:
ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[a1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4
请注意,在这种情况下,视频和音频将被重新编码 - 确保指定适当的输出质量目标(例如-crf
x264、x265 或 libvpx-vp9)。您可以在 FFmpeg Wiki 上阅读更多相关信息,例如VP9或者H.264。
使用单个段
如果您想要分割剪辑并稍后重新组合它们:
ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4
ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4
如果文件有音频,请使用与上述相同的方法:
ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4
这将再次重新编码视频流。这更简单一些,但其他方面应该与上述方法相同。
使用concat
解复用器
原则上,您也可以尝试使用 concat 解复用器连接比特流而无需重新编码。创建一个名为的文件concat.txt
并添加以下条目(对应于上面创建的视频剪辑):
file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'
然后连接这些单独的文件:
ffmpeg -f concat -i concat.txt -c copy output.avi
然而,这要求您的剪辑具有相同的编解码器、分辨率、帧速率等 - 因此它不适用于各种异构源。
使用concat
协议
上述类型的文件级连接concat
也可以使用该协议实现,具有与上述相同的约束(相同的编解码器,分辨率等):
ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4
有关串联的更多信息,请阅读相应的 FFmpeg Wiki 页面。