我想每隔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
。bitor
or
在两个表达式之间应用逻辑。-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)。
更新:
看起来-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
与使用选择过滤器相比,它的准确性稍差。