且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用FFMPEG:如何进行场景变化检测?有时间码?

更新时间:2023-02-06 16:04:50

结合场景过滤器(用于检测场景变化)和 showinfo 过滤器应该实现你想要的:

Combining the scene filter (for detecting scene changes) and the showinfo filter should achieve what you want:

ffmpeg -i input.flv  -filter:v "select='gt(scene,0.4)',showinfo"  -f null  - 2> ffout

此命令将与上一帧不同的所有帧提取超过( 0.4 (从 0 1 )。对于这些框架,信息将打印出来( showinfo )像这样

This command extracts all frames that differ from the previous frame by more than (gt) 0.4 (on a scale from 0 to 1). For these frames, information is printed out (showinfo) like this

[Parsed_showinfo_1 @ 0x2d85e60] n:   0 pts:2537204 pts_time:2.5372  pos:  2998114 fmt:rgb24 sar:1/1 s:1920x1200 i:P iskey:1 type:I checksum:5616582E plane_checksum:[5616582E]

现在你只需要提取时间戳。我想你对 pts_time 感兴趣。你可以这样做:

Now you only have to extract the timestamp. I think you're interested in pts_time. You could do it like this:

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

这将给您所有时间戳列表:

This will give you the list of all timestamps:

2.5372
4.37799
6.65301
8.09344

对于这种方法,您必须具有实现场景检测的FFmpeg版本。此外,您必须为第一个命令中的阈值( 0.4 )选择合适的值。您可以通过提取不同阈值的帧来尝试找到***阈值(并且之后手动检查帧)

For this approach to work, you must have a version of FFmpeg that implements the scene detection. Also, you have to select a suitable value for the threshold (0.4 in the first command). You can try to find an optimal threshold by extracting frames for different thresholds (and afterwards examine the frames manually) like this

ffmpeg -i input.flv -filter:v "select='gt(scene,0.1)',showinfo" -vsync 0 frames/%05d.jpg

只是为了澄清: grep [0-9。] * 不排除另一个答案中声明的整数。它匹配由数字和句点组成的任何字符序列,但它也将匹配非数字,如4.4.4。但是,ffmpeg不应该输出这些不合时宜的时间戳。

Just for clarification: grep [0-9.]* does not exclude integers as claimed in another answer. It matches any character sequence consisting of digits and periods but it would also match non-numbers like '4.4.4'. However, ffmpeg shouldn't output such ill-formed timestamps.