FFMPEG:如何在 GOP 边界/关键帧上*不*分割视频而不进行转码?

Mar*_*tos 2 video ffmpeg

使用 FFMPEG,如何将视频分成相等长度的片段,这些片段可能或可能不从关键帧开始?

假设您熟悉分段格式和break_non_keyframes选项,FFMPEG 似乎并没有达到我的预期(从我阅读的内容来看......无法再找到链接)。

ffmpeg -i ...  -f segment -break_non_keyframes 1 -segment_time 2 -c copy 2secs%03d.ts
Run Code Online (Sandbox Code Playgroud)

即,创建一个实际上可能比所需片段(根据需要包括整个 GOP)更长的片段。

例如,假设一个 3 帧 GOP,其愚蠢的帧速率为 1 FPS,具有以下愚蠢的 IBP 节奏:

 01 02 03 11 12 13 21 22 23 31 32 33
  I  B  P  I  B  P  I  B  P  I  B  P
Run Code Online (Sandbox Code Playgroud)

如果我想将其分成 2 秒的片段,则期望看到生成以下片段(括号中的帧不会显示在该片段中):

01 02 03  (03 not displayed in this segment, only used for decoding)
01 02 03 11 (... 01 and 02)
11 12 13  (... 11 )
21 22 23  (... 23)
21 22 23 31 (...21 22)
31 32 33  (... 31)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,每个片段中都会有额外的帧,但给定起始 PTS 和结束 PTS,您始终可以仅单独播放/转码该片段。

这确实浪费了空间(片段的总和将比原始资源大得多),但这不是重点。重点是拥有独立的片段而无需转码。

小智 5

遗憾的是,当前的分段复用器无法实现这一点。该break_non_keyframes选项针对的是 HLS 等情况,其中许多播放器将片段视为连续的数据包流,因此将参考数据拆分到多个文件中不是问题。

我很好奇你的实际用例是什么。您在哪里需要固定长度的段,每个段都必须可解码为完全独立的文件?我怀疑大多数玩家会按照你希望的方式处理这个问题;在没有参考图片的情况下,玩家通常会显示绿色或灰色伪影,而不是丢弃帧。

另外,你的 IBP 节奏有点误导。假设您的帧编号是显示顺序,则您的帧实际上在流中按 IPB/IPB/IPB/IPB 顺序排列。

如果您确实需要此功能,则可以(但并非完全微不足道)在分段复用器中实现。您需要缓冲传入的每个数据包,每次命中 IDR 帧时丢弃缓冲区,并将缓冲区写入您开始写入的下一个文件。

引文:我实现了该break_non_keyframes设置。