ffmpeg中时间戳调整参数setpts
PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
当视音频音画不同步,播放器进度条拖动异常,总时长显示异常,往往都是由于pts错误导致的。
先说如何查看视音频的pts
利用ffprobe命令查看每帧的数据, 以下命令会查看每一帧的相关参数,其中pkt_pts即该帧的pts
1 | ffprobe -show_frames input.mp4 |
如何设置pts
如果将每一帧的pts打印出来,你会发现这是个递增的数列(除了有B帧的情况),因为pts本身就是显示时间戳嘛,当然就是越靠后越大了。
那么修复pts,就是看如何重新构造这个递增的时间戳数列。
setpts这个参数本质上是ffmpeg中实现的功能,以filter的形式集成在ffmpeg的处理过程中,
ffmpeg会将本次命令执行过程中,涉及到的filter功能作为一个链,每一个视音频的帧,会首先由第一个filter开始处理,处理后的帧,传给下一个filter处理,等最后一个filter处理结束后,执行最后封装的过程。
那么在配置setpts这个参数时,我们主要是写出表达式,则当filter处理该帧,即根据表达式算出正确的pts,再写入到帧里。
表达式里可以用到的变量
1 | FRAME_RATE,FR |
在文档中 http://ffmpeg.org/ffmpeg-all.html 搜索setpts可以找到相关介绍。
以下列出一个实例,以供参考:
1 | ffmpeg -y -i input.ts -filter_complex "[0:1]asetpts='print(if(gt(PREV_INPTS, PTS), PREV_INPTS, if(gt(PREV_OUTPTS, PTS), PREV_OUTPTS, PTS)))',aresample=async=1000" -acodec libfdk_aac -vcodec copy output.ts |
看到这里的小伙伴,应该是真的需要用他来修复时间戳了,但这里有一个坑。
坑
用setpts转码过之后,再用ffprobe来看,发现转出来的视频pts跟你在setpts里算出来的不一样。
是因为ffmpeg默认在filter链里,帮你加了另外一个会改动pts的filter,那就是aresample。
可以看到日志里记录下了加fliter这一步骤
1 | [format_out_0_1 @ 0x2a89140] auto-inserting filter 'auto_resampler_0' between the filter 'Parsed_asetpts_0' and the filter 'format_out_0_1' |
所以为了去掉aresample对我们pts修复的影响,我们需要设置一下aresample这个参数,上面的例子,我加入了 aresample=async=1000 便是这个作用。
aresample怎么用,还是在文档里找吧 http://ffmpeg.org/ffmpeg-all.html