FFmpeg的GOP(I帧)对齐问题

起因

DSAH视频系统(服务器&播放器)搭建中,当使用mp4dash对多个分辨率的视频进行切片时,遇到了一个错误:

Parsing media file 1: f1080p.mp4
Parsing media file 2: f720p.mp4
Parsing media file 3: f480p.mp4
Parsing media file 4: f360p.mp4
Parsing media file 5: f144p.mp4
WARNING: video duration mismatch between "File 2#1" and "File 1#1"
WARNING: video duration mismatch between "File 3#1" and "File 2#1"
ERROR: video tracks are not aligned ("File 2#1" differs from File 1#1)

提示不同分辨率的Video Track没有对齐。通过查阅资料,发现应该是GOP(I帧)不对齐的问题。


溯源

在之前的编码中,已经通过-g 48明确指定了GOP长度(48帧,即2s),具体命令为:

ffmpeg -i elephants_dream_1080p24.y4m -s 1920x1080 -c:v libx264 -g 48 -an ED1920x1080.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 1280x720 -c:v libx264 -g 48 -an ED1280x720.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 896x504 -c:v libx264 -g 48 -an ED896x504.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 640x360 -c:v libx264 -g 48 -an ED640x360.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 256x144 -c:v libx264 -g 48 -an ED256x144.mp4

为了验证,使用上述命令重新编码了5个分辨率的视频,输出分别为:
1920x1080
1280x720
896x504
640x360
256x144
留意各图中第二行的frame I,可以看出,各个Track的I帧数量确实是不同的。

明明已经指定了GOP长度,为什么会出现这种情况呢?这是因为编码器会根据场景切换自动添加I帧(确切来说是IDR帧)。我们知道,I帧是帧内预测编码,即根据本帧的图像信息独立编码,不需要依赖其他帧;而B、P帧为帧间预测,会根据本帧与其他帧间的变化进行编码。帧间预测在画面变动不大的情况下可以明显降低视频码率,但是如果遇到了大的场景切换,效果就会很差。因此,编码器为了编码后的视频质量考虑,默认会进行场景识别,从而在合适的地方自动添加I帧——这也就导致了不同分辨率Track下的I帧不对齐问题。


解决

既然知道了原因,解决思路就很明确了。只需要在使用ffmpeg进行编码的时候引入两个选项即可:

  • -keyint_min 48:keyint表示关键帧(IDR帧)间隔,这个选项表示限制IDR帧间隔最小为48帧,与之前设置的GOP等长
  • -sc_threshold 0:禁用场景识别,即禁止自动添加IDR帧

因此,保证GOP对齐的编码命令应该为:

ffmpeg -i elephants_dream_1080p24.y4m -s 1920x1080 -c:v libx264 -keyint_min 48 -g 48 -sc_threshold 0 -an ED1920x1080.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 1280x720 -c:v libx264 -keyint_min 48 -g 48 -sc_threshold 0 -an ED1280x720.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 896x504 -c:v libx264 -keyint_min 48 -g 48 -sc_threshold 0 -an ED896x504.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 640x360 -c:v libx264 -keyint_min 48 -g 48 -sc_threshold 0 -an ED640x360.mp4
ffmpeg -i elephants_dream_1080p24.y4m -s 256x144 -c:v libx264 -keyint_min 48 -g 48 -sc_threshold 0 -an ED256x144.mp4

*不过,强制IDR帧对齐可能会导致视频质量下降

更为详细的信息,参见:

### 使用FFmpeg读取I 为了专门处理视频中的I(即时域预测的关键),可以利用`FFmpeg`强大的过滤器功能。一种方法是通过使用`select`滤镜来提取所有的I并将其保存为图像序列或新的视频文件。 以下是具体实现方式: #### 提取I作为图片序列 此命令会遍历输入视频并将每一个检测到的I导出成单独的JPEG文件[^1]。 ```bash ffmpeg -i input.mp4 -vf "select=eq(pict_type\,I)" -vsync vfr output_%03d.jpg ``` #### 创建仅含I的新视频 该指令创建一个新的MP4文件,只保留原始视频里的I而不改变其编码格式。 ```bash ffmpeg -i input.mp4 -vf "select=eq(pict_type\,I),setpts=N/FRAME_RATE/TB" -c:v libx264 -crf 18 -preset veryslow -an -y i_frames_only.mp4 ``` 上述操作中使用的选项解释如下: - `-vf "select=eq(pict_type,I)"`: 应用了一个名为`select`的视频滤波器,它会选择满足条件`pict_type==I`的画面; - `setpts=N/FRAME_RATE/TB`: 调整时间戳以适应新生成的内容结构; - `-c:v libx264`: 指定输出视频编解码器为H.264; - `-crf 18`: 设置恒定质量因子(CRF),数值越低表示压缩率越高而画质越好,在这里选择了相对较高的视觉质量; - `-an`: 去除音频流; - `-y`: 如果存在相同名称的目标文件则覆盖写入; 对于想要进一步探索更多关于`FFmpeg`的功能以及获取详细的帮助文档,可参照官方提供的全面指南,比如运行带有不同参数级别的帮助命令如`ffmpeg -h full`来查阅完整的配置项列表及其描述[^3]。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Green Lv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值