I try to get one frame from a remote RTSP source every 10 seconds so that I can get regular updates but avoid using too much CPU/bandwidth/IO resources. I am still figuring out how to do it. The most naive way should be running the following snippet every 10 seconds:
import cv2
import time
vcap = cv2.VideoCapture("rtsp://URL")
ret, frame = vcap.read()
if ret is True:
cv2.imwrite('screenshot1.png',frame)
print('done')
else:
print('error')
vcap.release()
It works! But it opens and closes the RTSP instance each time, which appears to be a waste. Also, it will flood my authentication log with this automatic login. I try to make it better by doing the following:
import cv2
import time
vcap = cv2.VideoCapture("rtsp://URL")
while True:
ret, frame = vcap.read()
if ret is True:
cv2.imwrite('screenshot2.png', frame)
print('done')
else:
print('error')
time.sleep(10)
The original idea is that, I keep the connection open but I only grab a frame every 10 seconds. The issue is, it doesn't work. My observation is that OpenCV will capture every frame from the resource, no matter if I call ret, frame = vcap.read()
. OpenCV saves those frames in an internal buffet, even if I wait for 10 seconds before calling ret, frame = vcap.read()
again, I still get the 2nd frame, not the expected 10 sec * 30 fps = 300th frame.
So my question is: is there a way that I can keep RTSP connection open but stop OpenCV from reading all the frames? (In my mind, I am thinking about something similar to a database connection--you can keep the connection without constantly doing SELECT
)
PS: I am aware that if I control the RTSP source, I could turn its FPS parameter down from something like 30 to 1. As a result, the process becomes much less resource-intensive. This is in fact the trick I am using. But I am thinking if it can do better than this.
PPS1: I find this similar question: Screenshot every 5 or 10 min from rtsp source using ffmpeg . But it appears to be using the naive approach--it opens the connection, grab a frame and close it, regularly.
PPS2: I also find this similar question: Getting current frame with OpenCV VideoCapture in Python. But it appears to be using the 2nd approach--it grabs all frames and just discard those unneeded ones. While this approach works, it does not save any resources at all.