FFmpeg的GOP(I帧)对齐问题

7 篇文章 0 订阅

起因

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帧对齐可能会导致视频质量下降

更为详细的信息,参见:

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
要使用FFmpeg截取I,可以通过以下步骤实现: 1. 首先,将输入的时间戳转换为FFmpeg的时间戳格式。在FFmpeg中,时间戳的单位是基于AV_TIME_BASE的,而输入的时间戳单位是秒。可以使用av_rescale()函数将其进行转换。 2. 接下来,需要使用FFmpeg的av_seek_frame()函数进行关键的定位。关键通常是I,因此可以通过定位关键来实现截取I的目的。 3. 在av_seek_frame()函数中,需要指定相关参数,包括输入的AVFormatContext、流索引、目标时间戳,以及seek_flag参数。 4. 设置seek_flag参数为AVSEEK_FLAG_BACKWARD,表示向后查找关键。这样可以确保定位到离目标时间戳最近的关键。 5. 调用av_seek_frame()函数后,可以获取到定位到的关键的时间戳。 请注意,以上步骤仅提供了一种实现截取I的方法,具体的实现方式可能会因应用场景和需求的不同而有所差异。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [FFMPEG SDK 快速截取I](https://blog.csdn.net/xiongsy1990/article/details/50605780)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [QT+FFMPEG 从摄像机拉取rtsp裸h264流,播放并保存到本地](https://download.csdn.net/download/asdasfdgdhh/13451538)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Green Lv

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

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

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

打赏作者

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

抵扣说明:

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

余额充值