![在 ffmpeg 中智能修剪 h.264 .MP4 视频文件](https://linux22.com/image/1483756/%E5%9C%A8%20ffmpeg%20%E4%B8%AD%E6%99%BA%E8%83%BD%E4%BF%AE%E5%89%AA%20h.264%20.MP4%20%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6.png)
我想将实时捕获的 H.264 视频作为输入,然后将其修剪为从黑色淡入淡出,以尽可能少的编码结束淡入淡出。这些淡入/淡出点可能位于 I 帧之间。如果不重新编码,则无法在非 I 帧处进行修剪。
我画了一张图:
我想将输入文件分成三部分。A 部分从点 1 之前的 I 帧开始,到点 1 结束。C 部分从点 2 的 I 帧开始,到淡入黑色后的下一个 I 帧结束。它们将被重新编码为全 I 帧格式。这两个片段相对较短,只有 10-30 秒。B 部分(大部分视频)只需使用 codec:copy 即可转码。
部分 A 和 C 将被修剪(自动使用黑场检测或手动),然后使用 ffmpeg 连接整个视频。
我想使用 ffmpeg,因为这是我最熟悉的,并且我的其余工作流程都只使用它。哪些命令行可以实现这一点?
好奇的读者可以看看我使用的命令行,它可将实时视频捕获为编码片段。从这一点开始,可以轻松丢弃不必要的视频,并根据需要重新编码片段以进行修剪。最后一步是连接这些片段。
ffmpeg -f dshow -rtbufsize 702000k -video_size 1920x1080 -framerate 29.97 -pixel_format uyvy422 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -threads 0 -c:v libx264 -s 1280x720 -crf 18 -profile:v main -level 3.1 -pix_fmt yuv420p -c:a libvo_aacenc -b:a 128k -ac 1 -f segment -segment_time 0.01 -reset_timestamps 1 seg%02d.mp4
答案1
这可以通过使用段复用器和连接解复用器来实现。
步骤1分割输入
假设您希望从捕获的源中提取00:50
。02:20
假设 GOP 大小为 3 秒。由于您的入点可能是 GOP 的最后一帧,因此我们需要提前一个 GOP 长度开始。因此,修剪开始时间为00:47
,提取持续时间为01:33
。因此,
ffmpeg -ss 0:47 -t 01:33 -i input.mp4 -c copy -f segment -segment_time 0.01 -reset_timestamps 1 seg%02d.mp4
这将创建片段,每个片段长度为一个 GOP。因此,不要将其用于帧内编码流 :)
第2步修剪头部和尾部
删除头部和尾部多余的片段 - 如果 GOP 长度较小,则可行。然后修剪正确的顶部和尾部片段:
ffmpeg -ss 2 -i seg00.mp4 -crf 18 -map [v] -map [a] seg00a.mp4
ffmpeg -t 2 -i seg46.mp4 -crf 18 -map [v] -map [a] seg46a.mp4
步骤3康卡特
A)准备 concat 文件segments.txt
file 's00a.mp4'
file 's01.mp4'
file 's02.mp4'
...
file 's44.mp4'
file 's45.mp4'
file 's46a.mp4'
b)
ffmpeg -f concat -i segments.txt -c copy -fflags +genpts trimmed.mp4
由于您正在进行实时捕获,因此除了最终输出之外,您可以输出到 TS 而不是 MP4。