
FFmpeg 压缩视频花屏排查
一个奇怪的视频压缩导致的花屏问题。
最近在开发我的新产品 OrbitSpace。
为了制作官网,我需要录制一段产品演示视频,放在首页作为 Showcase,因此整个流程其实非常简单:
录屏 → FFmpeg 压缩 → 上传 Cloudflare R2 → 官网在线播放
本以为这是整个发布流程中最轻松的一步,没想到却让我踩到了一个非常隐蔽的坑,也顺带学到了不少关于 MP4 时间轴、FFmpeg 和浏览器视频解码的知识。
这篇文章记录一下整个排查过程,希望以后有人遇到类似问题时,能少走一些弯路。
事情的开端
这段产品演示视频是使用录屏软件直接录制的,录制完成后导出为:origin.mp4。为了确认没有问题,我先在本地检查了一遍:
- ✅ QuickTime 正常
- ✅ IINA 正常
- ✅ 浏览器本地打开也正常
整个视频从头到尾没有任何异常,于是开始准备压缩,使用的是一条非常常见的 FFmpeg 命令:
整个压缩过程没有任何报错,直到我播放生成的视频。
一个诡异的现象
由于视频最终需要放到官网,我把压缩好的视频上传到了 Cloudflare R2,结果浏览器里完全无法播放,在播放到第 6 秒之后,直接停住了,整个流程看起来像这样:
第一反应:Cloudflare R2 把视频弄坏了?
因为问题是在上传之后暴露的,所以我的第一反应就是:
难道是 Cloudflare R2?
于是开始各种排查:
- 删除重新上传
- 新建 Bucket
- 换域名
- 清缓存
- 下载回来重新播放
结果发现下载回来的视频依然会在第 6 秒花屏,也就是说 R2 保存的是已经有问题的视频,真正的问题其实发生在上传之前。
第二个怀疑对象:FFmpeg
既然不是 R2,那自然开始怀疑 FFmpeg,于是我开始疯狂试参数,包括:
- CRF
- Preset
- Profile
- Level
- GOP
- Keyframe
- B Frame
几乎能试的都试了一遍,结果没有任何改善,依然是:
第 6 秒卡顿,本地播放花屏
这时候我才开始意识到一个问题,如果每次都坏在完全相同的位置,那它大概率不是编码质量的问题。
真正的突破:开始怀疑时间轴
后来查资料的时候,看到一句话让我突然意识到方向可能错了。
播放器能正常播放,不代表视频完全符合规范。
很多播放器都会自动帮用户做容错,例如:
- PTS 不连续
- DTS 跳变
- 可变帧率(VFR)
- 少量损坏帧
很多播放器会默默修复,所以用户根本感觉不到,但是 FFmpeg 在重新编码时,会继续使用这些时间信息。于是,原本隐藏的问题,被重新编码放大了。
最终解决方案
后来尝试重新整理整个视频时间轴,而不是单纯重新编码。
命令如下:
重新生成之后:
- ✅ QuickTime 正常
- ✅ Safari 正常
- ✅ Chrome 正常
- ✅ 上传 R2 正常
- ✅ 官网播放正常
整个问题彻底消失,而且实际上真正关键的是下面几个:
重新生成视频时间戳(PTS),如果录屏软件导出的时间信息有问题,这一步会重新计算。
把视频统一转换成固定帧率,很多录屏软件导出的是 VFR(Variable Frame Rate,可变帧率),统一之后,整个时间轴都会重新整理。
明确告诉 FFmpeg:输出必须是恒定帧率(CFR),这一步和上一条通常需要一起使用。
重新同步音频时间轴,虽然表面看是画面出了问题,但浏览器播放视频时,音视频时间轴其实是一起推进的。
重新同步之后,很多奇怪的问题都会一起消失。
保证浏览器和硬件解码兼容,它不是导致第 6 秒花屏的元凶,但 Web 视频几乎都会加上这一项。
为什么上传后更容易暴露问题?
首先要明确的一点是,Cloudflare R2 不会修改视频内容。对象存储保存的是原始字节,真正导致不同的是浏览器播放方式,浏览器不会一次下载完整视频,而是:
如果视频存在:
- 时间轴异常
- Sample Table 异常
- GOP 无法恢复
- 时间戳跳变
浏览器硬件解码器可能直接停止继续解码,于是表现出来就是:播放到第 6 秒,视频彻底停住,而 QuickTime 的容错能力明显更强,所以还能继续播放。
问题复盘
现在回头看,其实整个问题一直都存在,只不过原始的视频文件中,播放器帮我隐藏了问题。
真正的流程应该是这样:
所以真正的问题是:录屏软件导出的视频包含了一些播放器能够自动容错,但重新编码和浏览器硬件解码不会替你修正的时间轴信息。
也正因为如此,它直到压缩/上传 CDN 之后才第一次真正暴露出来。
给 Web 视频的一份推荐参数
如果视频最终需要部署到:
- 官网
- Cloudflare R2
- S3
- CDN
- Safari
- Chrome
- Edge
我现在直接使用下面这一套参数:
虽然参数比默认多了一些,但能够规避不少由于时间轴、可变帧率和播放器兼容性导致的隐蔽问题。
写在最后
在处理录屏软件生成的视频的时候,播放器为了保证用户体验,会默默帮我们处理很多问题。
只有当视频经历了:
- 重新编码
- 上传对象存储
- 浏览器在线播放
这一整套流程时,那些原本隐藏得很深的问题,才会真正暴露出来。
如果你也遇到了:
- FFmpeg 压缩后固定时间花屏
- 上传 Cloudflare R2 后播放卡住
- Safari 播放到一半停止
- 浏览器在线播放异常
建议第一时间检查:
- 视频时间戳(PTS / DTS)
- 是否是 VFR(可变帧率)
- 是否需要重新生成时间轴



