FFmpeg显示的PTS与MP4头stts/ctts导出PTS差异及计算方法问询
MP4 PTS 差异问题解析
1. FFmpeg 显示的 PTS 与 stts/ctts 解析结果不同的原因
- 时间基准自动转换:MP4 里 stts/ctts 存储的时间值是基于视频轨道的
timescale(媒体时间基,比如常见的 90000,代表 1 秒被拆分为 90000 个时间单位)的原始数值。而 FFmpeg 的showinfo滤镜显示的 PTS,是已经转换为该流内部使用的time_base(可能和媒体时间基不同,比如采用微秒级基准)的数值,并且会自动对齐到播放起始点的 0 时刻。 - edts 编辑列表的处理:如果你的 MP4 包含
edts编辑列表,说明视频轨道存在时间偏移(比如原始媒体前有无效帧,编辑后从中间某帧开始播放)。FFmpeg 会自动减去这个偏移,让播放时间线从 0 开始;但直接解析 stts/ctts 得到的是媒体本身的原始时间,未考虑该偏移,因此数值会出现差异。 - 帧时序的自动校正:若视频包含 B 帧,ctts 表会记录 DTS 到 PTS 的偏移,但 FFmpeg 会自动完成转换并对齐播放时序;手动解析时若未正确处理 ctts 的正负偏移,也可能出现差异,但你遇到的第一帧差异更可能由前两个原因导致。
2. 从 stts、ctts、edts 正确推导 PTS 的步骤
按以下流程操作:
- 获取轨道 timescale:从 MP4 的
moov->trak->mdia->mdhd字段中取出timescale,这个值是将时间单位转换为秒的关键。 - 计算每帧的 DTS:
- 遍历
stts表的每个条目,每个条目包含sample_count(该段的帧数)和sample_delta(每帧的 DTS 增量)。 - 初始 DTS 设为 0,依次累加每个帧的 delta,得到每帧的原始 DTS(单位为 timescale 的时间单位)。
- 遍历
- 计算原始 PTS:
- 遍历
ctts表的每个条目,每个条目包含sample_count和sample_offset(PTS 相对 DTS 的偏移值)。 - 对每帧使用公式
PTS = DTS + sample_offset得到原始媒体 PTS(注意 offset 可能为负数,对应 B 帧的情况)。
- 遍历
- 应用 edts 调整(若存在):
- 如果轨道存在
edts编辑列表,找到第一个 edit entry 的media_time(媒体起始偏移时间),将每帧的原始 PTS 减去这个值,得到的就是播放时的 PTS(与 FFmpeg 显示的数值对应)。
- 如果轨道存在
- 转换为秒数:将最终的 PTS 值除以
timescale,即可得到以秒为单位的 PTS(比如你的例子中 0.0667s,应该是原始 PTS 为 6000、timescale 为 90000,6000/90000=0.0667)。
内容的提问来源于stack exchange,提问作者userDtrm
相关产品推荐
相关产品推荐

