每隔 X 秒从实时流中创建一个图像

每隔 X 秒从实时流中创建一个图像

我想每隔X秒(比如2秒)从CCTV直播中抓取一张静态图像。

我尝试了一下,大约需要 6 秒钟 – 可能是因为协议协商。ffmpeg -rtsp_transport udp -i rtsp://user:[email protected]:554/front -r 1 -vf scale="-1:720" -vframes 1 -y latest.jpg -loglevel error

所以我想也许可以让 ffmpeg 持续运行 - 尝试添加-r 1来实现这一点。或者让一个 ffmpeg 实例处理流,这样初始协议协商只需发生一次并将其传送到另一个 ffmpeg?

示例流

答案1

根据文件选择过滤器表达式求值,我们可以按时间来选择帧。

每 2 秒选择一帧:

ffmpeg -y -loglevel error -rtsp_transport udp -i rtsp://user:[email protected]:554/front -vf "select=bitor(gte(t-prev_selected_t\,2)\,isnan(prev_selected_t))",scale="-1:720" -vsync 0 img_%05d.jpg

解释:

  • isnan(prev_selected_t)1-在第一个视频帧中返回(0否则)。
  • gte(t-prev_selected_t\,2)返回1如果cur_frame_time - prev_selected_frame_time >= 2
  • bitoror在两个表达式之间应用逻辑。
  • -vsync 0- 视频同步方法passthrough- 每帧都带有其时间戳。

如果你知道帧速率,你可以选择每 n 帧,如下所述这个帖子

例如,假设帧速率为 25fps。
选择每 50 帧:

ffmpeg -y -loglevel error -rtsp_transport udp -i rtsp://user:[email protected]:554/front -vf "select=not(mod(n\,50))",scale="-1:720" -vsync 0 img_%05d.jpg

通过将合成的 RTSP 视频流传输到本地主机进行测试:

在第一个控制台执行:

按时间:

ffmpeg -rtsp_flags listen -rtsp_transport udp -stimeout 1000000 -i rtsp://127.0.0.1:31415/live.stream -vf "select=not(mod(n\,500))",scale="-1:72" -vsync 0 img_%05d.jpg

或者:

按帧号:

start ffmpeg -rtsp_flags listen -rtsp_transport udp -stimeout 1000000 -i rtsp://127.0.0.1:31415/live.stream -vf "select=bitor(gte(t-prev_selected_t\,20)\,isnan(prev_selected_t))",scale="-1:72" -vsync 0 img_%05d.jpg

在第二个控制台中执行:

ffmpeg -re -f lavfi -i testsrc=size=192x108:rate=25 -vcodec libx264 -pix_fmt yuv420p -rtsp_transport udp -f rtsp -bsf:v dump_extra rtsp://127.0.0.1:31415/live.stream

该示例每 20 秒获取一帧(并调整大小为 128x72)。

示例输出
img_00001.jpg::
在此处输入图片描述

img_00002.jpg
在此处输入图片描述

img_00003.jpg
在此处输入图片描述


更新:

看起来-r 0.05(或者-r 0.5在你的情况下)也有效:

ffmpeg -rtsp_flags listen -rtsp_transport udp -stimeout 1000000 -i rtsp://127.0.0.1:31415/live.stream -vf scale="-1:72" -r 0.05 -vsync 2 img_%05d.jpg

与使用选择过滤器相比,它的准确性稍差。

相关内容