Question / Help [SOLVED] OBS not reloading ip camera stream

Soultrader

New Member
thius issue is still happening even now in 2019. and it's really annoying - the vlc fix does not work either for me and i'm no programmer so don't understand about the autoit thing.

could anyone help me if i give you my ip setup etc?
 
Last edited:

RomJosh

New Member
Hi there. I'm also facing the problem and working on a Python script to work around it. The strategy is to check if we can actually retrieve data from a source and update its properties if not.
Does someone have an idea of a function from the OBS API to check if a source is actually connected and sending data?
 

Soultrader

New Member
Just FYI - adding the rtsp address as a vlc source on it's own did not work, however adding it several times to the 'playlist' did work - i added it 10 times.

also FYI the streamlabs version of OBS has no issues with losing the rtsp stream at all.
 

pabo

New Member
Here it is. Something to work on, but it does the job.

Written in AutoIt.
- You need to install AutoIt in order to compile/run this script.​
- I recommend you also install SciTE to edit the file (to set some variables such as camera's IP address).​
Tested under Windows 7 64-bit (x86).
Should work on WinXP and above.
No VLC required.



Code:
; 2017-08-03
; //// Monitoring the TCP connection between obs32.exe and the ip camera (RTSP port 554) ////
; - If OBS isn't open yet, opens and starts streaming
; - Attempts to restart ip camera connection when lost
;
; NOTE:
; PRELIMINARY VERSION
; WARNING - as it is, it creates a logfile; if things don't go as planned, the log file can become VERY LARGE!
; (let's say 10MB per hour)
;
;
; ADAPTED FROM:
; NETWORK CONNECTIONS VIEWER, written by trancexx
; https://www.autoitscript.com/forum/topic/87581-check-a-tcp-ip-connection/


; exits if another instance is already running
#include <Misc.au3>
If _Singleton("ConnView_STRIPED_DOWN", 1) = 0 Then
    __Log("FATAL ERROR: Another instance of this program is already running. Exiting...")
    Exit
EndIf


#include <Array.au3>
Global Const $sFullPath = "C:\Program Files (x86)\obs-studio\bin\32bit\"
Global Const $sPIDname = "obs32.exe"
Global Const $sWinTitle = "[TITLE:OBS; CLASS:Qt5QWindowIcon]"
Global Const $sWinText = "obs32"
Global Const $sProfile = "Untitled" ; profile name - if no match, opens profile from last execution
Global Const $sCollection = "Untitled" ; scene collection name - if no match, opens scene collection from last execution
Global Const $sRemoteIP = "192.168.1.64" ; your camera ip
Global Const $iRemotePort = 554 ; RTSP port
Global Const $iSleepTime = 2000 ; delay to check for connection
Global Const $sSendHide = "{CTRLDOWN}{ALTDOWN}{SHIFTDOWN}H{CTRLUP}{ALTUP}{SHIFTUP}" ; OBS hotkey to hide media (stop)
Global Const $sSendShow = "{CTRLDOWN}{ALTDOWN}{SHIFTDOWN}S{CTRLUP}{ALTUP}{SHIFTUP}" ; OBS hotkey to show media (play)


Opt("MustDeclareVars", 1)
Opt("WinWaitDelay", 0) ; 0 ms

Global Const $hNTDLL = DllOpen("ntdll.dll")
Global Const $hKERNEL32 = DllOpen("kernel32.dll")
Global Const $hUSER32 = DllOpen("user32.dll")
Global Const $hIPHLPAPI = DllOpen("iphlpapi.dll")
Global Const $hWS232 = DllOpen("ws2_32.dll")
Global Const $hPSAPI = DllOpen("psapi.dll")
Global Const $hWTSAPI32 = DllOpen("wtsapi32.dll")
Global Const $hADVAPI32 = DllOpen("advapi32.dll")


Global $aTCPArray



Global $hLog = FileOpen("log.txt", 1)
Func __Log($comment)
    Local $sLine =  __DATETIME()&@TAB&$comment
    ConsoleWrite("-> (Logged) " & $sLine & @CRLF)
    FileWriteLine($hLog, $sLine)
EndFunc




; START LOOP
While 1
    While Not ProcessExists($sPIDname)
        __Log("ERROR: Process """ & $sPIDname & """ not found. Starting process...")
        ShellExecute ($sFullPath&$sPIDname, "--profile """&$sProfile&""" --collection """&$sCollection&""" --startstreaming", $sFullPath)
        ProcessWait($sPIDname, $iSleepTime*5)
        ;Exit -2
    WEnd

    $aTCPArray = _CV_GetExtendedTcpTable()
    If @error Then
        __Log("FATAL ERROR: Unable to get TCP table. Exiting...")
        Exit -2
    EndIf

    ;_ArrayDisplay($aTCPArray, "TCP Table")

    If UBound($aTCPArray) < 1 Then
        __Log("Connection not found between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort)
        __Restart_Media()
    Else
        If UBound($aTCPArray) > 1 Then
            __Log("WARNING: More than one connection exists between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort)
        EndIf

        For $i = 0 To UBound($aTCPArray) - 1
            If $aTCPArray[$i][2] <> "ESTABLISHED" Then
                __Log("ERROR: Connection between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort & " has state """ & $aTCPArray[$i][2] & """")
                __Restart_Media()
            Else
                ConsoleWrite("+> " & __DATETIME()&@TAB& "IP Camera stream connection to OBS seems to be ok" & @CRLF)
            EndIf
        Next
    EndIf

    Sleep($iSleepTime)
WEnd



Func _CV_GetExtendedTcpTable()

    Local $aCall = DllCall($hIPHLPAPI, "dword", "GetExtendedTcpTable", _
            "ptr*", 0, _
            "dword*", 0, _
            "int", 1, _ ; 1, sort in ascending order
            "dword", 2, _ ; AF_INET4
            "dword", 5, _ ; TCP_TABLE_OWNER_PID_ALL
            "dword", 0)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    If $aCall[0] <> 122 Then ; ERROR_INSUFFICIENT_BUFFER
        Return SetError(2, 0, 0)
    EndIf

    Local $iSize = $aCall[2]

    Local $tByteStructure = DllStructCreate("byte[" & $iSize & "]")

    $aCall = DllCall($hIPHLPAPI, "dword", "GetExtendedTcpTable", _
            "ptr", DllStructGetPtr($tByteStructure), _
            "dword*", $iSize, _
            "int", 1, _ ; 1, sort in ascending order
            "dword", 2, _ ; AF_INET4
            "dword", 5, _ ; TCP_TABLE_OWNER_PID_ALL
            "dword", 0)

    If @error Or $aCall[0] Then
        Return SetError(3, 0, 0)
    EndIf

    Local $tMIB_TCPTABLE_OWNER_PID_DWORDS = DllStructCreate("dword[" & Ceiling($iSize / 4) & "]", DllStructGetPtr($tByteStructure))

    Local $iTCPentries = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1)

    Local $aConnections[$iTCPentries][3] ; PID_Name | PID_Number | Connection_state

    Local $aState[12] = ["CLOSED", "LISTENING", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "FIN_WAIT1", "FIN_WAIT2", "CLOSE_WAIT", "CLOSING", "LAST_ACK", "TIME_WAIT", "DELETE_TCB"]

    Local $aProcessList = ProcessList()
    ;_ArrayDisplay($aProcesses)

    Local $iOffset
    Local $iIP

    Local $sIP = ""
    Local $iPort_LOCAL = 0

    TCPStartup()

    Local $iArrayElement = 0

    For $i = 1 To $iTCPentries

        $iOffset = ($i - 1) * 6 + 1 ; going thru array of dwords

        If DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 1) < 3 Then
            ; ignore generic connections
            ContinueLoop
        Else
            $iIP = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 4)
            $sIP = BitOR(BinaryMid($iIP, 1, 1), 0) & "." & BitOR(BinaryMid($iIP, 2, 1), 0) & "." & BitOR(BinaryMid($iIP, 3, 1), 0) & "." & BitOR(BinaryMid($iIP, 4, 1), 0)
            If $sIP <> $sRemoteIP Then
                ContinueLoop
            Else ; this is the remote IP that we want to monitor
                $iPort_LOCAL = Dec(Hex(BinaryMid(DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 5), 1, 2)))
                If $iPort_LOCAL == $iRemotePort Then ; this is the intended port that we want to monitor
                    ;ConsoleWrite("!!!!! found ip and port" & @CRLF)
                    $aConnections[$iArrayElement][2] = $aState[DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 1) - 1] ; Connection state
                    $aConnections[$iArrayElement][1] = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 6) ; PID_Number
                    For $j = 1 To $aProcessList[0][0]
                        If $aProcessList[$j][1] == $aConnections[$iArrayElement][1] Then
                            $aConnections[$iArrayElement][0] = $aProcessList[$j][0]
                            ExitLoop
                        EndIf
                    Next
                    If $aConnections[$iArrayElement][0] <> $sPIDname Then
                        ContinueLoop ; ignore this connection because it's not from the intended process name.
                    Else
                        $iArrayElement += 1
                    EndIf
                EndIf
            EndIf
        EndIf

    Next

    TCPShutdown()

    _ArrayDelete($aConnections, $iArrayElement & "-" & UBound($aConnections)-1)

    Return $aConnections

EndFunc   ;==>_CV_GetExtendedTcpTable






Func __Send_Show()
    __Log("Showing Media")
    Local $hWinHandle = WinGetHandle($sWinTitle,$sWinText)
    SendKeepActive($hWinHandle)
    Send($sSendShow)
EndFunc




Func __Send_Hide()
    __Log("Hiding Media")
    Local $hWinHandle = WinGetHandle($sWinTitle,$sWinText)
    SendKeepActive($hWinHandle)
    Send($sSendHide)
EndFunc




Func __Restart_Media()
    __Send_Hide()

    __Log("Ping")
    While Ping($sRemoteIP,1000) == 0
        ConsoleWrite("!> " & __DATETIME()&@TAB& "Ping timeout" & @CRLF)
    WEnd

    __Log("Port test")
    TCPStartup()
    While TCPConnect($sRemoteIP, $iRemotePort) < 1
        ConsoleWrite("!> " & __DATETIME()&@TAB& "Can't open ip camera port "&$iRemotePort & @CRLF)
        Sleep(1000)
    WEnd
    TCPShutdown()

    __Send_Show()
EndFunc



Func __DATETIME()
    Return @YEAR&"-"&@MON&"-"&@MDAY&" "&@HOUR&":"&@MIN&":"&@SEC&"."&@MSEC
EndFunc
This still works great. Thanks.

I'm currently trying to troubleshoot WHY my IP cams disconnect when another wifi client connects, but at least until I solve that, my stream will auto reconnect to them once they are back up.
 

PeeBee2021

New Member
Hi All,

Brand new to OBS and am trying to allow OBS to reconnect to the stream if it drops out, the same as all above.

My source will be a camera from an aircraft, streaming to a ground station, and at the moment I am replicating that stream with VLC as a source on one server. This is being picked up by my 'Streaming Server' in OBS and forwarding it out using the rtsp plugin.

It is working extremely well, until the stream drops out and comes back online. When it comes back online OBS doesnt pick it back up.

I have been trying to implement the workaround provided by @Ground Loop. But I cant seem to get it working.

1. I have AutoIT.
2. I changed the script parameters to include the path to OBS (I tried both the 64 & 32 Bit versions).
3. I input the IP address of the server that has the VLC RTSP stream, and the port. VLC needs to have a "/" at the end or it won't work for me. How do I include this in the script? Do I need to?
4. When I compile and run the script, OBS runs, and I get a message "Invalid Path or Connection URL. Please check your settings to confirm that they are valid". I presume this is because of the missing / in the script?
5. In the log file I get the following:

Connection not found between "obs32.exe" and IP Address 192.X.X.X at port 8554.
Hiding Media
Ping
Port test
Showing Media
Connection not found between "obs32.exe" and IP Address 192.X.X.X at port 8554.
Hiding Media
Ping
Port test
Showing Media ..... AND SO ON...

I know have the Path right, as if I didnt OBS wouldn't start when I run the script.

I am running Windows server 2019, so have adjusted the Paths accordingly from the original code provided.


Any help would be greatly appreciated,

Thanks a mil,

PeeBee
 

bekahugs

New Member
I'm having this same issue and now its 2021... Is the script still the best solution out there? I've got 6 cameras running and they freeze or go blank all the time. I just upgraded my computer and I think ti got worse!
 

assembilly

New Member
I still have the same problem!!! The only ip camera (hikvision) I am using loses connection once a day! I am streaming 24/7 on YouTube through obs but it's always the same, the streaming stops, although obs still broadcasts unstoppable the black screen.. when I just click on the camera settings it reconnects and works again (I guess because a new rtsp request happens)
 

Pacific

New Member
Here it is. Something to work on, but it does the job.

Written in AutoIt.
- You need to install AutoIt in order to compile/run this script.​
- I recommend you also install SciTE to edit the file (to set some variables such as camera's IP address).​
Tested under Windows 7 64-bit (x86).
Should work on WinXP and above.
No VLC required.



Code:
; 2017-08-03
; //// Monitoring the TCP connection between obs32.exe and the ip camera (RTSP port 554) ////
; - If OBS isn't open yet, opens and starts streaming
; - Attempts to restart ip camera connection when lost
;
; NOTE:
; PRELIMINARY VERSION
; WARNING - as it is, it creates a logfile; if things don't go as planned, the log file can become VERY LARGE!
; (let's say 10MB per hour)
;
;
; ADAPTED FROM:
; NETWORK CONNECTIONS VIEWER, written by trancexx
; https://www.autoitscript.com/forum/topic/87581-check-a-tcp-ip-connection/


; exits if another instance is already running
#include <Misc.au3>
If _Singleton("ConnView_STRIPED_DOWN", 1) = 0 Then
    __Log("FATAL ERROR: Another instance of this program is already running. Exiting...")
    Exit
EndIf


#include <Array.au3>
Global Const $sFullPath = "C:\Program Files (x86)\obs-studio\bin\32bit\"
Global Const $sPIDname = "obs32.exe"
Global Const $sWinTitle = "[TITLE:OBS; CLASS:Qt5QWindowIcon]"
Global Const $sWinText = "obs32"
Global Const $sProfile = "Untitled" ; profile name - if no match, opens profile from last execution
Global Const $sCollection = "Untitled" ; scene collection name - if no match, opens scene collection from last execution
Global Const $sRemoteIP = "192.168.1.64" ; your camera ip
Global Const $iRemotePort = 554 ; RTSP port
Global Const $iSleepTime = 2000 ; delay to check for connection
Global Const $sSendHide = "{CTRLDOWN}{ALTDOWN}{SHIFTDOWN}H{CTRLUP}{ALTUP}{SHIFTUP}" ; OBS hotkey to hide media (stop)
Global Const $sSendShow = "{CTRLDOWN}{ALTDOWN}{SHIFTDOWN}S{CTRLUP}{ALTUP}{SHIFTUP}" ; OBS hotkey to show media (play)


Opt("MustDeclareVars", 1)
Opt("WinWaitDelay", 0) ; 0 ms

Global Const $hNTDLL = DllOpen("ntdll.dll")
Global Const $hKERNEL32 = DllOpen("kernel32.dll")
Global Const $hUSER32 = DllOpen("user32.dll")
Global Const $hIPHLPAPI = DllOpen("iphlpapi.dll")
Global Const $hWS232 = DllOpen("ws2_32.dll")
Global Const $hPSAPI = DllOpen("psapi.dll")
Global Const $hWTSAPI32 = DllOpen("wtsapi32.dll")
Global Const $hADVAPI32 = DllOpen("advapi32.dll")


Global $aTCPArray



Global $hLog = FileOpen("log.txt", 1)
Func __Log($comment)
    Local $sLine =  __DATETIME()&@TAB&$comment
    ConsoleWrite("-> (Logged) " & $sLine & @CRLF)
    FileWriteLine($hLog, $sLine)
EndFunc




; START LOOP
While 1
    While Not ProcessExists($sPIDname)
        __Log("ERROR: Process """ & $sPIDname & """ not found. Starting process...")
        ShellExecute ($sFullPath&$sPIDname, "--profile """&$sProfile&""" --collection """&$sCollection&""" --startstreaming", $sFullPath)
        ProcessWait($sPIDname, $iSleepTime*5)
        ;Exit -2
    WEnd

    $aTCPArray = _CV_GetExtendedTcpTable()
    If @error Then
        __Log("FATAL ERROR: Unable to get TCP table. Exiting...")
        Exit -2
    EndIf

    ;_ArrayDisplay($aTCPArray, "TCP Table")

    If UBound($aTCPArray) < 1 Then
        __Log("Connection not found between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort)
        __Restart_Media()
    Else
        If UBound($aTCPArray) > 1 Then
            __Log("WARNING: More than one connection exists between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort)
        EndIf

        For $i = 0 To UBound($aTCPArray) - 1
            If $aTCPArray[$i][2] <> "ESTABLISHED" Then
                __Log("ERROR: Connection between """ & $sPIDname & """ and IP address " & $sRemoteIP & " at port " & $iRemotePort & " has state """ & $aTCPArray[$i][2] & """")
                __Restart_Media()
            Else
                ConsoleWrite("+> " & __DATETIME()&@TAB& "IP Camera stream connection to OBS seems to be ok" & @CRLF)
            EndIf
        Next
    EndIf

    Sleep($iSleepTime)
WEnd



Func _CV_GetExtendedTcpTable()

    Local $aCall = DllCall($hIPHLPAPI, "dword", "GetExtendedTcpTable", _
            "ptr*", 0, _
            "dword*", 0, _
            "int", 1, _ ; 1, sort in ascending order
            "dword", 2, _ ; AF_INET4
            "dword", 5, _ ; TCP_TABLE_OWNER_PID_ALL
            "dword", 0)

    If @error Then
        Return SetError(1, 0, 0)
    EndIf

    If $aCall[0] <> 122 Then ; ERROR_INSUFFICIENT_BUFFER
        Return SetError(2, 0, 0)
    EndIf

    Local $iSize = $aCall[2]

    Local $tByteStructure = DllStructCreate("byte[" & $iSize & "]")

    $aCall = DllCall($hIPHLPAPI, "dword", "GetExtendedTcpTable", _
            "ptr", DllStructGetPtr($tByteStructure), _
            "dword*", $iSize, _
            "int", 1, _ ; 1, sort in ascending order
            "dword", 2, _ ; AF_INET4
            "dword", 5, _ ; TCP_TABLE_OWNER_PID_ALL
            "dword", 0)

    If @error Or $aCall[0] Then
        Return SetError(3, 0, 0)
    EndIf

    Local $tMIB_TCPTABLE_OWNER_PID_DWORDS = DllStructCreate("dword[" & Ceiling($iSize / 4) & "]", DllStructGetPtr($tByteStructure))

    Local $iTCPentries = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1)

    Local $aConnections[$iTCPentries][3] ; PID_Name | PID_Number | Connection_state

    Local $aState[12] = ["CLOSED", "LISTENING", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "FIN_WAIT1", "FIN_WAIT2", "CLOSE_WAIT", "CLOSING", "LAST_ACK", "TIME_WAIT", "DELETE_TCB"]

    Local $aProcessList = ProcessList()
    ;_ArrayDisplay($aProcesses)

    Local $iOffset
    Local $iIP

    Local $sIP = ""
    Local $iPort_LOCAL = 0

    TCPStartup()

    Local $iArrayElement = 0

    For $i = 1 To $iTCPentries

        $iOffset = ($i - 1) * 6 + 1 ; going thru array of dwords

        If DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 1) < 3 Then
            ; ignore generic connections
            ContinueLoop
        Else
            $iIP = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 4)
            $sIP = BitOR(BinaryMid($iIP, 1, 1), 0) & "." & BitOR(BinaryMid($iIP, 2, 1), 0) & "." & BitOR(BinaryMid($iIP, 3, 1), 0) & "." & BitOR(BinaryMid($iIP, 4, 1), 0)
            If $sIP <> $sRemoteIP Then
                ContinueLoop
            Else ; this is the remote IP that we want to monitor
                $iPort_LOCAL = Dec(Hex(BinaryMid(DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 5), 1, 2)))
                If $iPort_LOCAL == $iRemotePort Then ; this is the intended port that we want to monitor
                    ;ConsoleWrite("!!!!! found ip and port" & @CRLF)
                    $aConnections[$iArrayElement][2] = $aState[DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 1) - 1] ; Connection state
                    $aConnections[$iArrayElement][1] = DllStructGetData($tMIB_TCPTABLE_OWNER_PID_DWORDS, 1, $iOffset + 6) ; PID_Number
                    For $j = 1 To $aProcessList[0][0]
                        If $aProcessList[$j][1] == $aConnections[$iArrayElement][1] Then
                            $aConnections[$iArrayElement][0] = $aProcessList[$j][0]
                            ExitLoop
                        EndIf
                    Next
                    If $aConnections[$iArrayElement][0] <> $sPIDname Then
                        ContinueLoop ; ignore this connection because it's not from the intended process name.
                    Else
                        $iArrayElement += 1
                    EndIf
                EndIf
            EndIf
        EndIf

    Next

    TCPShutdown()

    _ArrayDelete($aConnections, $iArrayElement & "-" & UBound($aConnections)-1)

    Return $aConnections

EndFunc   ;==>_CV_GetExtendedTcpTable






Func __Send_Show()
    __Log("Showing Media")
    Local $hWinHandle = WinGetHandle($sWinTitle,$sWinText)
    SendKeepActive($hWinHandle)
    Send($sSendShow)
EndFunc




Func __Send_Hide()
    __Log("Hiding Media")
    Local $hWinHandle = WinGetHandle($sWinTitle,$sWinText)
    SendKeepActive($hWinHandle)
    Send($sSendHide)
EndFunc




Func __Restart_Media()
    __Send_Hide()

    __Log("Ping")
    While Ping($sRemoteIP,1000) == 0
        ConsoleWrite("!> " & __DATETIME()&@TAB& "Ping timeout" & @CRLF)
    WEnd

    __Log("Port test")
    TCPStartup()
    While TCPConnect($sRemoteIP, $iRemotePort) < 1
        ConsoleWrite("!> " & __DATETIME()&@TAB& "Can't open ip camera port "&$iRemotePort & @CRLF)
        Sleep(1000)
    WEnd
    TCPShutdown()

    __Send_Show()
EndFunc



Func __DATETIME()
    Return @YEAR&"-"&@MON&"-"&@MDAY&" "&@HOUR&":"&@MIN&":"&@SEC&"."&@MSEC
EndFunc

What else parameters like FullPath, PIDname, Wintext, ipaddress should I modify the program for obs64.exe? I'm not sure about the internal files like .dll, etc. Anyone, please help.
 
Top