pythonrtspffprobe

Python: Prevent script from stopping or hanging when RTSP from application fails


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.

enter image description here

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


Solution

  • 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.