FFmpeg 拆分视频并合并回来

Ari*_*ana 15 video mp4 ffmpeg video-conversion video-encoding

我正在尝试使用 FFmpeg 根据某些start_timeend_time输入拆分视频,并将其替换为其他视频文件。例如,对于输入,10 15我需要10 to 15用另一个视频替换 EXACT 秒。

好的。我想到的是这样的:

  1. 首先拆分视频(在本例中为 0-10、10-15 和 15-end)
  2. 用其他视频替换 10-15
  3. 合并所有子视频

第一个问题:这是最好和最快的解决方案吗?我们是否有更简单的命令或其他工具来用另一个视频替换视频中的特定时间段?

第二个问题:假设FFmpeg是可行的解决方案,当我简单地使用命令时ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4,我的视频处理代码无法读取和处理文件。我使用mediainfo工具来比较这两个文件并注意到标头大小的差异,而所有与视频编解码器相关的内容都相同。我注意到 HEADER SIZE 不同,这显然是导致问题的原因。是否有任何方法可以强制标题大小(编解码器除外)也相同?

更新:这是.mp4在模拟器中运行良好的原始文件

slh*_*hck 20

使用trimconcat– 具有不同编解码器的源文件

为此,请确保您的各个文件具有相同的分辨率,并且理想情况下具有相同的帧率和色度子采样等。这将防止连接过程中出现错误或故障。

使用trimconcat过滤器,您可以一次性完成所有操作而无需拆分文件:

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
Run Code Online (Sandbox Code Playgroud)

此处,trim用于指定稍后要连接的输入视频流 ( 0:v, 1:v)的各个部分。这些部分v0通过v2. (setpts过滤器将这些单独部分的时间戳重置为 0,这是串联所必需的)。稍后,我们将三个部分连接起来。

如果要从某个时间戳修剪到结尾,请使用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[v1]; \
[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
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,视频和音频将被重新编码——确保指定适当的输出质量目标(例如,-crf对于 x264、x265 或 libvpx-vp9)。您可以在 FFmpeg Wiki 上阅读更多相关信息,例如VP9H.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
Run Code Online (Sandbox Code Playgroud)

如果文件有音频,请使用与上述相同的方法:

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
Run Code Online (Sandbox Code Playgroud)

这将再次重新编码视频流。它更简单一些,但在其他方面应该与上述方法等效。

使用concat分路器

原则上,您也可以尝试使用 concat demuxer 连接位流而不重新编码它们。创建一个名为的文件concat.txt并添加以下条目(对应于上面创建的视频剪辑):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'
Run Code Online (Sandbox Code Playgroud)

然后连接这些单独的文件:

ffmpeg -f concat -i concat.txt -c copy output.avi
Run Code Online (Sandbox Code Playgroud)

然而,这要求您的剪辑具有相同的编解码器、分辨率、帧率等——因此它不适用于所有类型的异构源。

使用concat协议

上述类型的文件级连接也可以使用concat协议来实现,具有与上述相同类型的约束(相同的编解码器、分辨率等):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4
Run Code Online (Sandbox Code Playgroud)

有关串联的更多信息,请阅读相应的 FFmpeg Wiki 页面