I am streaming a video feed (RTSP) and doing analytics on it. The code works fine but it just hangs after a long streaming period. I put Wireshark on it and found, for the most part, that the server (10.61.41.4) is sending a Keep-alive, the client is responding with ACK but no data is returned from the server. The client sends a reset, hence the Retransmissions. At this point, I guess, the stream application (server) has just stop, for whatever reason. I don't have control over the server. If the application has restarted, the script does not know, continues in the hang state.
My question is: what methods can I use with code to detect the script when it hangs for more than say 30 seconds, then restart the entire script. I figure its the easiest way than to peer into the TCP stream and fetch the TCP Retransmissions if more than 4.
I have implemented ffprobe.exe, thinking it would return something to say the stream is present or not, but it does not return anything when the stream has disconnected. I am using ffprobe.exe cause it has a quicker timeout if nothing is present over opencv - cv2.VideoCapture(). However this appears only to work when the script starts, not under the conditions just described.
Thinking I am not using the correct args in cmnd to get a result when stream has stopped, or should I use another method?
def probe_stream(path, cam_name):
cmnd = [r'C:\ffmpeg-2022\bin\ffprobe.exe', '-rtsp_transport', 'tcp', '-show_format',
'-pretty', '-loglevel', 'quiet', '-of', 'json', path]
p = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(p)
print(p.communicate())
s = p.communicate()[0]
print(s)
if p.returncode == 0:
out, err = p.communicate()
p.wait()
probe_dct = json.loads(out)
try:
if probe_dct:
return True
elif err:
print(err)
except Exception as e:
print(e)
thanks
After much google. there are a couple of options.
I used ffprode.exe because the opencv CAP timeout was too slow when there is no steam. A solution is to recompile opencv to shorted the CAP timeout, but could not be bothered doing that. Another is to add a flag, either cv.CAP_FFMPEG or cv.CAP_DSHOW to cv2.VideoCapture(), e.g.cv2.VideoCapture(0, cv.CAP_DSHOW) . Both work and shorten the time to a few seconds. CAP_DSHOW appears to tell opencv to immediately display the video and not wait. CAP_FFMPEG does similar but uses the FFMPEG library, which what I was trying to originally do.
To use FFMPEG, need to set the environment prior to CAP, either TCP or UDP. os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;tcp'
openCV flags here.