背景
工作中遇到的呗。记下来贡着。
滤镜重置时间戳:setpts=PTS-STARTPTS
在FFmpeg中,setpts=PTS-STARTPTS
是一种用于调整视频时间戳(PTS)的滤镜表达式。这个表达式通常用于视频编辑和处理过程中,用于修改视频的时间轴。
让我们解释一下这个表达式的各个部分:
PTS
:表示当前帧的原始时间戳(针对滤镜的输入而言,而非原始文件)。时间戳是用于确定视频中每一帧的时刻的数值。在ffmpeg执行过程中,这是个动态值!
STARTPTS
:表示流的开始时间戳。这是输入流的第一帧的时间戳。在一个处理链中,STARTPTS用于引用流的初始时间戳,而不是每一帧的时间戳。这是个确定的值,等于滤镜拿到的「视频流的开始时间戳」,在ffmpeg执行过程中,恒定不变。这里强调一下,滤镜内trim
指定的起始时间(不指定则默认0)如果还没有出现视频流,则STARTPTS
会一直向后找到视频流,把遇到的首帧时间戳作为其值。
PTS-STARTPTS
(相减):这部分表示当前帧相对于开始时间戳的偏移量。使用这个表达式会将视频的时间轴重新设置,以使第一帧的时间戳为零,后续帧的时间戳相对于第一帧进行调整。
setpts
:这是一个滤镜指令,用于设置帧的新时间戳。通过将setpts
与PTS-STARTPTS
结合使用,可以重新计算和调整视频帧的时间戳。
综合起来,setpts=PTS-STARTPTS
的效果是将视频的时间轴重新调整,使第一帧的时间戳为零,后续帧相对于第一帧进行相应的时间调整。这在一些视频处理场景中很有用,例如剪辑、拼接或进行时间轴变换。
另外,滤镜的输入,是-ss -t 等参数裁剪完之后的结果,这个结果的时间戳从0开始。所以对于滤镜来说,滤镜拿到的输入文件的时间戳总是起始于0。但是,视频流却未必起始于0。例如,-ss -t裁剪完,传给滤镜的文件 总时长10秒,但视频流只在7~10秒(也就是前7秒没画面),那么STARTPTS
值恒为7,PTS
值为变量,即每一帧的时间戳(起始于STARTPTS
)。
案例一:滤镜不重置时间戳
ffmpeg -ss 10 -stream_loop -1 -i dongwu_25min.mp4 -t 30 -filter_complex "[0:v]scale=1920:1080,trim=start=5.000000:duration=10.000,showinfo[node1_f2_media1]" -map "[node1_f2_media1]" -y output.mp4
注意:滤镜中的duration=10.000
会严格取视频流的持续时长,如有空白则跳过。
打印中间信息:
[Parsed_showinfo_2 @ 0x6000026b0160] n: 1 pts: 64538 pts_time:5.04203 duration: 512 duration_time:0.04 pos: 6978739 fmt:yuv420p sar:1/1 s:1920x1080 i:P iskey:1 type:I checksum:6E67BBE3 plane_checksum:[4C14CFED 616C9631 542B55B6] mean:[114 114 140] stdev:[46.7 10.5 8.2]
[Parsed_showinfo_2 @ 0x6000026b0160] color_range:tv color_space:bt709 color_primaries:bt709 color_trc:bt709
[Parsed_showinfo_2 @ 0x6000026b0160] n: 2 pts: 65050 pts_time:5.08203 duration: 512 duration_time:0.04 pos: 7073379 fmt:yuv420p sar:1/1 s:1920x1080 i:P iskey:0 type:B checksum:7F7442B0 plane_checksum:[5183AB5E C054091B A25D8E28] mean:[114 114 140] stdev:[46.9 10.5 8.3]
[Parsed_showinfo_2 @ 0x6000026b0160] color_range:tv color_space:bt709 color_primaries:bt709 color_trc:bt709
[Parsed_showinfo_2 @ 0x6000026b0160] n: 3 pts: 65562 pts_time:5.12203 duration: 512 duration_time:0.04 pos: 7082240 fmt:yuv420p sar:1/1 s:1920x1080 i:P iskey:0 type:B checksum:A5B5226D plane_checksum:[EC5F922E 1D3CB01D 4CF5E004] mean:[113 114 140] stdev:[47.0 10.5 8.3]
# .........
[Parsed_showinfo_2 @ 0x6000026b0160] n: 248 pts: 191002 pts_time:14.922 duration: 512 duration_time:0.04 pos: 11124238 fmt:yuv420p sar:1/1 s:1920x1080 i:P iskey:0 type:P checksum:2DD2E7F0 plane_checksum:[C0E163CA 3CD3F5D4 0B798E43] mean:[118 116 138] stdev:[38.6 7.5 6.8]
[Parsed_showinfo_2 @ 0x6000026b0160] color_range:tv color_space:bt709 color_primaries:bt709 color_trc:bt709
[Parsed_showinfo_2 @ 0x6000026b0160] n: 249 pts: 191514 pts_time:14.962 duration: 512 duration_time:0.04 pos: 11221829 fmt:yuv420p sar:1/1 s:1920x1080 i:P iskey:0 type:B checksum:46C2FCF7 plane_checksum:[129AED32 F4604F36 708DC080] mean:[118 116 138] stdev:[38.6 7.5 6.8]
[Parsed_showinfo_2 @ 0x6000026b0160] color_range:tv color_space:bt709 color_primaries:bt709 color_trc:bt709
frame= 375 fps= 60 q=-1.0 Lsize= 4848kB time=00:00:14.88 bitrate=2669.2kbits/s dup=125 drop=0 speed=2.39x
video:4843kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.104424%
[libx264 @ 0x128006460] frame I:2 Avg QP:17.26 size: 95752
产出视频总时长15秒,前5秒静止为首帧。原因是时间戳保留为滤镜的输入,即输入流从第5秒才开始出现。
案例二:滤镜重置时间戳
ffmpeg -ss 10 -stream_loop -1 -i dongwu_25min.mp4 -t 30 -filter_complex "[0:v]scale=1920:1080,trim=start=5.000000:duration=10.000,setpts=PTS-STARTPTS,showinfo[node1_f2_media1]" -map "[node1_f2_media1]" -y output.mp4
由于设置了setpts=PTS-STARTPTS
,视频流导出后的时间戳从0开始。注意-t
最好给足,不然滤镜拿到的视频流可能不够用而导致产出视频变短。
案例三:讨论-i -ss -t 顺序问题
情况1: -ss -t -i (可能不符合预期)
ffmpeg -ss 8 -t 4 -i _part1.mp4 -y output.mp4
-ss
是截取输入文件的时间戳,-t
是视频流的最大持续时长。如果-ss
指定的开始时间有一段时间不含视频流,那么-t
的截取会跳过这段空白,直到找到视频流才计算时长。
如图视频的视频流是第10秒才开始有,则-ss 8 -t 4 -i a.mp4
的情况下,实际产物总时长6秒,且只有后4秒有视频流。
情况2: -ss -i -t (强烈推荐使用)
ffmpeg -ss 8 -i _part1.mp4 -t 4 -y output.mp4
-ss
是截取输入文件的时间戳,-t
是输出文件的最大持续时长。如果-ss
指定的开始时间有一段时间不含视频流,那么-t
的截取不会跳过这段空白。
-t
在-i
之前和之后的区别
-t
在-i
之前,则持续时长是针对-i
输入文件的流而言;-i
在-t
之前,则持续时长是针对输出文件而言。
情况3:-i -ss -t(慎用)
ffmpeg -i _part1.mp4 -ss 14:8 -t 4 -y output.mp4
-ss
是截取输入文件解码后的时间戳,-t
是输出文件的最大持续时长。
-ss
在-i
之前和之后的区别
-ss
在-i
之前,则截取的起始是针对-i
输入文件(不是流)而言;-i
在-ss
之前,则截取起始时间是针对解码后加粗样式的文件而言,比如-ss 20:00
会浪费性能为前20分钟解码。
关于滤镜中的duration和PTS
滤镜中的duration
会严格截取视频流的时长,有空白则跳过。
时间戳PTS如果设的超出预期时长,则还是会按时间戳播放,从而导致总时长变长。