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

问题描述 投票:0回答:4

根据这篇文章,似乎可以使用 FFMPEG 来检测视频中的场景变化: http://www.luckydinosaur.com/u/ffmpeg-scene-change- detector

现在我有一个视频,显示书籍文本,当说出文本(单词或句子)时,它会突出显示。 像这样的有声读物:https://youtu.be/lA7L6ZNVKjc

我需要知道文本突出显示时的时间戳(因此场景发生变化),这将允许我在 YouTube 视频上添加时间戳标签,以便听众更轻松地浏览有声读物。

可以执行此操作的magic命令行是什么?

非常感谢!

video ffmpeg ffprobe
4个回答
52
投票

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

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

此命令提取与前一帧相差超过 (

gt
)
0.4
(范围从
0
1
)的所有帧。对于这些框架,信息会像这样打印出来(
showinfo

[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
感兴趣。你可以这样做:

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

这将为您提供所有时间戳的列表:

2.5372
4.37799
6.65301
8.09344

要使这种方法发挥作用,您必须有一个实现场景检测的 FFmpeg 版本。此外,您还必须为阈值选择合适的值(第一个命令中的

0.4
)。您可以尝试通过提取不同阈值的帧来找到最佳阈值(然后手动检查帧),如下所示

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

仅供澄清:

grep [0-9.]*
不排除另一个答案中声称的整数。它匹配由数字和句点组成的任何字符序列,但也匹配非数字,如“4.4.4”。但是,ffmpeg 不应该输出这种格式错误的时间戳。


21
投票

您可以简单地使用命令:

ffmpeg -i inputvideo.mp4 -filter_complex "select='gt(scene,0.3)' -frame_pts true ,metadata=print:file=time.txt" -vsync vfr img%03d.png

这将仅将相关信息保存在 time.txt 文件中,如下所示。

frame:0    pts:108859  pts_time:1.20954
lavfi.scene_score=0.436456
frame:1    pts:285285  pts_time:3.16983
lavfi.scene_score=0.444537
frame:2    pts:487987  pts_time:5.42208
lavfi.scene_score=0.494256
frame:3    pts:904654  pts_time:10.0517
lavfi.scene_score=0.462327
frame:4    pts:2533781 pts_time:28.1531
lavfi.scene_score=0.460413
frame:5    pts:2668916 pts_time:29.6546
lavfi.scene_score=0.432326

该帧是从开始检测到的镜头变化的序号。另外,根据您的用例适当选择阈值(此处为 0.3)以获得正确的输出


9
投票

我没有代表对上述答案发表评论,但我想指出 @ckoehn 和 @keypulsations 发布的 grep 只会获取浮点时间戳。要获取浮点和整数时间戳,请使用以下正则表达式

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep -E '[0-9]+(?:\.[0-9]*)?' -o > timestamps

3
投票

我正在尝试 @ckoehn 答案,它有效,直到它停止工作,最后一个 grep 中的星号引起了麻烦。为了避免这种情况,我建议在 grep 句子中使用双引号,例如:

grep showinfo ffout | grep pts_time:[0-9.]* -o | grep "[0-9.]*" -o > timestamps
© www.soinside.com 2019 - 2024. All rights reserved.