使用ffmpeg从视频中提取多个图像并获取提取图像的时间戳

时间:2014-06-26 14:35:43

标签: video ffmpeg

我正在使用ffmpeg每隔五分钟从视频中提取一帧(作为jpeg),并将控制台的输出汇总到文本文件,以获得所提取帧的确切时间戳。

我正在使用的命令是:

ffmpeg -i input.avi -ss 00:10:00 -vframes 10 -vf showinfo,fps=fps=1/300 %03d.jpg &> output.txt

-ss 00:10:00允许我在开始之前在视频中向前跳过10分钟,-vframes 10让我只捕捉前10帧(每5分钟1帧)。

这几乎可以正常工作,除了命令输出所有帧的信息,包括那些未写为jpeg的帧。这是一个三行示例输出:

[Parsed_showinfo_0 @ 0x2219020] n:11427 pts:11429 pts_time:599.979 pos:48892180 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:6309A75D plane_checksum:[15A29007 1617E1FE D93A3549] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]
[Parsed_showinfo_0 @ 0x2219020] n:11428 pts:11430 pts_time:600.031 pos:48898094 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:B checksum:815D031A plane_checksum:[E004E973 E28CE2D5 F56636B4] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]
[Parsed_showinfo_0 @ 0x2219020] n:11429 pts:11431 pts_time:600.084 pos:48892448 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:6CE2D3C5 plane_checksum:[E983BD86 38B9E198 93B13498] mean:[146 125 153 ] stdev:[17.6 1.0 2.1 ]

我希望pts_time:600.031的中间线是作为图像提取的第一帧,但无法将其与任何一侧的其他帧区分开来,而不提取图像。

有没有人知道解决这个问题的方法?

谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用-vf showinfo使用ffmpeg获取帧信息。例如,当场景改变时提取帧并获得该特定帧的时间戳。

ffmpeg -i image.mp4 -filter:v "select='gt(scene,0.1)',showinfo" -vsync 0 frames%05d.jpg >& output.txt

您将输出类似的内容:[Parsed_showinfo_1 @ 0x25bf900] n:0 pts:119357 pts_time:9.95637 ....我们感兴趣的部分是pts_time,获取时间使用以下命令:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep '[0-9]*\.[0-9]*' -o > timestamps

您将获得类似的输出:

9.95637
9.98974
15.0281
21.8016
28.208
28.4082
28.5083

答案 1 :(得分:0)

在回答我自己的问题时,我现在找到了一种解决方法,但我并不确定它是如何工作的。通过在select中定义-vf参数并添加vsync 0参数,如下所示:

ffmpeg -i input.avi -vframes 10 -vf '[in]select=not(mod(n\,300*19.05))[s1];[s1]showinfo[out]' -vsync 0 %02d.jpg >& output.txt

...该功能现在仅返回所需的10帧。这是前两帧的示例stderr输出:

[Parsed_showinfo_1 @ 0x21b1b60] n:0 pts:2 pts_time:0.104992 pos:10248 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:1 type:I checksum:F6FDCFBF plane_checksum:[5FB6331C 9D9D7F99 44FB1D0A] mean:[183 126 155 ] stdev:[19.6 0.8 2.8 ]
frame=    1 fps=0.0 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=1.0 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.7 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.5 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.4 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.3 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.3 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.2 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
frame=    1 fps=0.2 q=4.1 size=N/A time=00:00:00.15 bitrate=N/A    
[Parsed_showinfo_1 @ 0x21b1b60] n:1 pts:5717 pts_time:300.121 pos:24474150 fmt:yuv420p sar:1/1 s:640x480 i:P iskey:0 type:P checksum:BAECD030 plane_checksum:[F609470E 45F694CE 4BFCF445] mean:[148 126 152 ] stdev:[17.7 0.8 2.3 ]
frame=    2 fps=0.4 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.4 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.3 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A    
frame=    2 fps=0.2 q=2.1 size=N/A time=00:05:00.17 bitrate=N/A   

仍然不确定为什么这会有效或者为什么每个frame= ...在输出中被复制了很多次,但它似乎可以完成这项工作!

答案 2 :(得分:0)

另外,来自" -ss"的ffmpeg文档。论点:

  

当用作输入选项(在-i之前)时,在此输入文件中寻找位置。请注意,在大多数格式中,无法精确搜索,因此ffm​​peg将在位置之前寻找最接近的搜索点。

因此/应该/返回的帧是n:11427处的帧。