Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; VLCManager.au3
- ;
- ; Execute and watchdog VLC Instances for video stream transcoding and broadcast
- ;
- ; Current architecture
- ; VLC Broadcaster 01: Pulls RTSP stream from rtsp://admin:password@camera.example.com/profile5/media.smp
- ; Broadcasts it locally via RTSP at rtsp://10.0.0.100:10122/camera02.sdp
- ;
- ; VLC Trancoder 01: pulls Broadcaster 01 RTSP stream from rtsp://10.0.0.100:10122/camera02.sdp
- ; transcodes to 480x320 MJPEG available at: http://10.0.0.100:82/camera02.jpg
- ;
- ; VLC Trancoder 02: pulls Broadcaster 01 RTSP stream from rtsp://10.0.0.100:10122/camera02.sdp
- ; transcodes to HLS available at: http://10.0.0.100:81/frontgate.m3u8
- ;
- ; VLC Trancoder 03: pulls Broadcaster 01 RTSP stream from rtsp://10.0.0.100:10122/camera02.sdp
- ; transcodes to native resolution MJPEG available at: http://10.0.0.100:83/camera02.jpg
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Notes
- ;
- ; - The Transcoders rely on the Broadcaster. If the Broadcaster dies, kill the Transcoders, start the Broadcaster,
- ; then restart the Transcoders.
- ;
- ; - VLC Transcoder 02 relies on IIS to share out .TS chunks saved in a RAM drive at v:\frontgate-1080
- ;
- ; - We'll also need to monitor that folder for disk space and clear it out between every run. If it runs out of
- ; space while the process is running, kill the process, clear it out, then start the process again.
- ;
- ; - VLC Transcoder 2 should be kicking out files every 5 seconds or so. If the folder doesn't have any files that
- ; have been updated in the last 60 seconds, kill the process, clear it out, then start the process again.
- ;
- ; - HLS transcoding doesn't seem to work on VLC 2.2.0 or 2.2.1. For now HLS will run on 2.1.5.
- #AutoIt3Wrapper_icon=VLCProcessManager.ico
- #RequireAdmin
- #include <Date.au3>
- #include <Array.au3>
- #include <File.au3>
- #include <MsgBoxConstants.au3>
- #include <FileConstants.au3>
- #include <InetConstants.au3>
- OnAutoItExitRegister("MyProcessCleanup")
- Opt("TrayAutoPause", 0)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Define global values
- Global $strBroadcast01Dir = "vlc-2.1.5"
- Global $strBroadcast01Cmd = "vlc.exe --no-crashdump -I dummy --play-and-exit rtsp://admin:password@camera.example.com/profile5/media.smp --sout=#rtp{name=camera.example.com,sdp=rtsp://10.0.0.100:10122/camera02.sdp}"
- Global $strBroadcast01Title = "VLC Broadcast 01: camera02 (Front Yard) to RTSP @ rtsp://10.0.0.100:10122/camera02.sdp"
- Global $strTranscode01Dir = "vlc-2.1.5"
- Global $strTranscode01Cmd = "vlc.exe --no-crashdump -I dummy --play-and-exit rtsp://10.0.0.100:10122/camera02.sdp --sout=#transcode{acodec=none,vcodec=mjpg,vb=512,width=480,height=320}:standard{access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:82/camera02.jpg}"
- Global $strTranscode01Title = "VLC Transcode 01: camera02 (Front Yard) to MJPEG @ http://10.0.0.100:82/camera02.jpg"
- Global $strTranscode02Dir = "vlc-2.1.5"
- Global $strTranscode02Cmd = "vlc.exe --no-crashdump -I dummy --play-and-exit rtsp://10.0.0.100:10122/camera02.sdp --sout=#transcode{width=1920,height=1080,fps=24,vb=2048,vcodec=h264,venc=x264{aud,profile=high,preset=ultrafast,keyint=24},acodec=aac,ab=96}:std{access=livehttp{seglen=1,delsegs=true,numsegs=3,index=V:\frontgate-1080\frontgate-1080.m3u8,index-url=frontgate-1080-########.ts},mux=ts{use-key-frames},dst=v:\frontgate-1080\frontgate-1080-########.ts}"
- Global $strTranscode02Title = "VLC Transcode 02: camera02 (Front Yard) to HLS @ http://10.0.0.100:81/frontgate.m3u8"
- Global $strTranscode03Dir = "vlc-2.1.5"
- Global $strTranscode03Cmd = "vlc.exe --no-crashdump -I dummy --play-and-exit rtsp://10.0.0.100:10122/camera02.sdp --sout=#transcode{acodec=none,vcodec=mjpg}:standard{access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:83/camera02.jpg}"
- Global $strTranscode03Title = "VLC Transcode 03: camera02 (Front Yard) to MJPEG @ http://10.0.0.100:83/camera02.jpg"
- Global $strHLSTempFolder = "V:\frontgate-1080"
- Global $intProcessCheckInterval = 5000
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Initialize the script
- ; Clear out anything in the HLS output folder
- FileDelete ($strHLSTempFolder)
- ; Run the Broadcast 01
- ; This is a bit weird because AutoIt is shit at console apps. Here we're calling cmd.exe plus the start command to get a separate console window started with the title set as we want it
- Run (@ComSpec & ' /c start "' & $strBroadcast01Title & '" ' & $strBroadcast01Cmd, $strBroadcast01Dir, @SW_HIDE)
- Local $hBroadcast01Window = WinWait ($strBroadcast01Title, "", 10)
- If Not $hBroadcast01Window Then
- MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), "VLC Process Manager", "ERROR: Failed to launch initial Broadcast 01 task. Exiting.")
- Exit(1)
- EndIf
- ; Run the Transcode 01
- Run (@ComSpec & ' /c start "' & $strTranscode01Title & '" /LOW ' & $strTranscode01Cmd, $strTranscode01Dir, @SW_HIDE)
- Local $hTranscode01Window = WinWait ($strTranscode01Title, "", 10)
- If Not $hTranscode01Window Then
- MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), "VLC Process Manager", "ERROR: Failed to launch initial Transcode 01 task. Exiting.")
- Exit(1)
- EndIf
- ; Run the Transcode 02
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" /LOW ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- Local $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- If Not $hTranscode02Window Then
- MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), "VLC Process Manager", "ERROR: Failed to launch initial Transcode 02 task. Exiting.")
- Exit(1)
- EndIf
- ; Run the Transcode 03
- Run (@ComSpec & ' /c start "' & $strTranscode03Title & '" /LOW ' & $strTranscode03Cmd, $strTranscode03Dir, @SW_HIDE)
- Local $hTranscode03Window = WinWait ($strTranscode03Title, "", 10)
- If Not $hTranscode03Window Then
- MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), "VLC Process Manager", "ERROR: Failed to launch initial Transcode 03 task. Exiting.")
- Exit(1)
- EndIf
- RecordInformationEvent("Initial startup complete.")
- ; Wait a check interval for things to light up
- Sleep ($intProcessCheckInterval)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Main monitoring loop
- While 1
- Sleep ($intProcessCheckInterval)
- ; Check if Broadcast 01 is running
- if not WinExists ($hBroadcast01Window) Then
- RecordErrorEvent("Broadcast 01 failure.")
- ; Kill transcode processes and clean out the HLS temp folder
- WinKill ($hTranscode01Window)
- WinKill ($hTranscode02Window)
- WinKill ($hTranscode03Window)
- FileDelete ($strHLSTempFolder)
- ; Re-launch the broadcast and the transcode processes
- Run (@ComSpec & ' /c start "' & $strBroadcast01Title & '" ' & $strBroadcast01Cmd, $strBroadcast01Dir, @SW_HIDE)
- $hBroadcast01Window = WinWait ($strBroadcast01Title, "", 10)
- Run (@ComSpec & ' /c start "' & $strTranscode01Title & '" ' & $strTranscode01Cmd, $strTranscode01Dir, @SW_HIDE)
- $hTranscode01Window = WinWait ($strTranscode01Title, "", 10)
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- Run (@ComSpec & ' /c start "' & $strTranscode03Title & '" ' & $strTranscode03Cmd, $strTranscode03Dir, @SW_HIDE)
- $hTranscode03Window = WinWait ($strTranscode03Title, "", 10)
- ContinueLoop
- EndIf
- ; Check if Transcode 01 is running
- if not WinExists ($hTranscode01Window) Then
- RecordErrorEvent("Transcode 01 failure.")
- Run (@ComSpec & ' /c start "' & $strTranscode01Title & '" ' & $strTranscode01Cmd, $strTranscode01Dir, @SW_HIDE)
- $hTranscode01Window = WinWait ($strTranscode01Title, "", 10)
- ContinueLoop
- EndIf
- ; Check if Transcode 02 is running
- if not WinExists ($hTranscode02Window) Then
- RecordErrorEvent("Transcode 02 failure.")
- FileDelete ($strHLSTempFolder)
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- ContinueLoop
- EndIf
- ; Check if Transcode 03 is running
- if not WinExists ($hTranscode03Window) Then
- RecordErrorEvent("Transcode 03 failure.")
- Run (@ComSpec & ' /c start "' & $strTranscode03Title & '" ' & $strTranscode03Cmd, $strTranscode03Dir, @SW_HIDE)
- $hTranscode03Window = WinWait ($strTranscode03Title, "", 10)
- ContinueLoop
- EndIf
- ; Check to make sure we are updating the HLS folder, if not, check again after another check interval,
- ; then restart Transcode 02 if we're still not updating
- If Not CheckFolderFilesAreUpdating($strHLSTempFolder) Then
- Sleep ($intProcessCheckInterval)
- If Not CheckFolderFilesAreUpdating($strHLSTempFolder) Then
- RecordErrorEvent("Transcode 02 HLS output folder not updating.")
- WinKill ($hTranscode02Window)
- FileDelete ($strHLSTempFolder)
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- ContinueLoop
- EndIf
- EndIf
- ; Check if we're running out of space for HLS, trigger at 5MB free
- Local $intHLSTempFolderFree = DriveSpaceFree ($strHLSTempFolder)
- if $intHLSTempFolderFree <= 5 Then
- RecordErrorEvent("Transcode 02 HLS output folder out of space.")
- WinKill ($hTranscode02Window)
- FileDelete ($strHLSTempFolder)
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- ContinueLoop
- EndIf
- ; Check to see if we have a different VLC error, if so, click no and the next loop will catch the missing
- ; process and do the needful
- Local $strVlcStoppedErrorWindow = WinGetTitle ("VLC media player", "Close the program")
- if $strVlcStoppedErrorWindow Then
- RecordErrorEvent("VLC has stopped working dialog.")
- WinActivate ($strVlcStoppedErrorWindow)
- Send("{ENTER}")
- ContinueLoop
- EndIf
- ; Check to see if we have a MSVC runtime error, if so, click no and the next loop will catch the missing
- ; process and do the needful
- Local $strMsvcErrorWindow = WinGetTitle ("Microsoft Visual C++ Runtime Library", "Runtime Error!")
- if $strMsvcErrorWindow Then
- RecordErrorEvent("MS Visual C++ runtime error.")
- WinActivate ($strMsvcErrorWindow)
- Send("{ENTER}")
- ContinueLoop
- EndIf
- ; Check to see if we have a VLC error, if so, click no and the next loop will catch the missing
- ; process and do the needful
- Local $strVlcErrorWindow = WinGetTitle ("VLC", "Ooops: VLC media player just crashed")
- if $strVlcErrorWindow Then
- RecordErrorEvent("VLC crash report dialog.")
- WinActivate ($strVlcErrorWindow)
- Send("!n")
- ContinueLoop
- EndIf
- ; Check if Broadcast 01 RTSP port is open
- If Not CheckTCPPortOpen("10.0.0.100", "10122") Then
- RecordErrorEvent("Broadcast 01 RTSP port check 10.0.0.100:10122 failed.")
- ; Kill broadcast and transcode processes and clean out the HLS temp folder
- WinKill ($hBroadcast01Window)
- WinKill ($hTranscode01Window)
- WinKill ($hTranscode02Window)
- FileDelete ($strHLSTempFolder)
- ; Re-launch the broadcast and the transcode processes
- Run (@ComSpec & ' /c start "' & $strBroadcast01Title & '" ' & $strBroadcast01Cmd, $strBroadcast01Dir, @SW_HIDE)
- $hBroadcast01Window = WinWait ($strBroadcast01Title, "", 10)
- Run (@ComSpec & ' /c start "' & $strTranscode01Title & '" ' & $strTranscode01Cmd, $strTranscode01Dir, @SW_HIDE)
- $hTranscode01Window = WinWait ($strTranscode01Title, "", 10)
- Run (@ComSpec & ' /c start "' & $strTranscode02Title & '" ' & $strTranscode02Cmd, $strTranscode02Dir, @SW_HIDE)
- $hTranscode02Window = WinWait ($strTranscode02Title, "", 10)
- EndIf
- ; Check if Transcode 01 MJPEG is kicking out data
- If Not ServiceCheckMjpeg("http://10.0.0.100:82/camera02.jpg") Then
- RecordErrorEvent("Transcode 01 MJPEG service check http://10.0.0.100:82/camera02.jpg failed.")
- ; Kill Transcode 01 processes
- WinKill ($hTranscode01Window)
- ; Re-start Transcode 01
- Run (@ComSpec & ' /c start "' & $strTranscode01Title & '" ' & $strTranscode01Cmd, $strTranscode01Dir, @SW_HIDE)
- $hTranscode01Window = WinWait ($strTranscode01Title, "", 10)
- ContinueLoop
- EndIf
- ; Check if Transcode 03 MJPEG is kicking out data
- If Not ServiceCheckMjpeg("http://10.0.0.100:83/camera02.jpg") Then
- RecordErrorEvent("Transcode 03 MJPEG service check http://10.0.0.100:83/camera02.jpg failed.")
- ; Kill Transcode 03 processes
- WinKill ($hTranscode03Window)
- ; Re-start Transcode 03
- Run (@ComSpec & ' /c start "' & $strTranscode03Title & '" ' & $strTranscode03Cmd, $strTranscode03Dir, @SW_HIDE)
- $hTranscode03Window = WinWait ($strTranscode03Title, "", 10)
- ContinueLoop
- EndIf
- WEnd ;==> End main loop
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Functions
- ; If we exit the script, close the running VLC instances
- Func MyProcessCleanup()
- if IsDeclared("hTranscode01Window") Then
- WinKill ($hTranscode01Window)
- EndIf
- if IsDeclared("hTranscode02Window") Then
- WinKill ($hTranscode02Window)
- EndIf
- if IsDeclared("hTranscode03Window") Then
- WinKill ($hTranscode03Window)
- EndIf
- if IsDeclared("hBroadcast01Window") Then
- WinKill ($hBroadcast01Window)
- EndIf
- FileDelete ($strHLSTempFolder)
- EndFunc ;==>MyProcessCleanup
- ; Hand this function a folder name (no trailing backslash), it will return 1 if there is a file that has been touched in the last 60 seconds
- ; cribbed heavily from: https://www.autoitscript.com/forum/topic/86878-script-to-check-folders-for-new-files
- Func CheckFolderFilesAreUpdating($Folder)
- Local $iTimeDeltaTarget = 60
- Local $avFiles = _FileListToArray($Folder & "\", "*", $FLTA_FILES)
- If @Error<>0 Then
- Return (False)
- EndIf
- Local $iNewestTime = 11111111111111; YYYYMMDDhhmmss set to an old time
- Local $iNewestIndex = 0; Array index of newest file
- ; Find the newest file
- For $p = 1 To $avFiles[0]
- ;ConsoleWrite($avFiles[$p] & " ")
- $iFileTime2 = Number(FileGetTime($Folder & "\" & $avFiles[$p], $FT_MODIFIED, $FT_STRING))
- ;ConsoleWrite($iFileTime2 & @CRLF)
- If $iFileTime2 > $iNewestTime Then
- $iNewestTime = $iFileTime2
- $iNewestIndex = $p
- EndIf
- Next
- ;ConsoleWrite("Newest file found: " & $avFiles[$iNewestIndex] & @CRLF)
- If $iNewestIndex > 0 Then
- Local $t = FileGetTime($Folder & "\" & $avFiles[$iNewestIndex])
- Local $iTimeDelta = _DateDiff( 's', $t[0] & "/" & $t[1] & "/" & $t[2] & " " & $t[3] & ":" & $t[4] & ":" & $t[5], _NowCalc())
- ;ConsoleWrite("$iTimeDelta: " & $iTimeDelta & @CRLF)
- If $iTimeDelta > $iTimeDeltaTarget Then
- ; Newest file is older than $iTimeDeltaTarget seconds
- ;ConsoleWrite(_DateTimeFormat( _NowCalc(),0) & " The files in: " & $Folder & " have NOT been updated in the last minute." & @CRLF & $avFiles[$iNewestIndex] & " is the newest file with a modified date of " & $t[1] & "/" & $t[2] & "/" & $t[0] & " " & $t[3] & ":" & $t[4] & ":" & $t[5] & @CRLF)
- Return (False)
- Else
- ; Newest file is NOT older than $iTimeDeltaTarget seconds
- ;ConsoleWrite(_DateTimeFormat( _NowCalc(),0) & " The files in: " & $Folder & " have been updated in the last minute." & @CRLF & $avFiles[$iNewestIndex] & " is the newest file with a modified date of " & $t[1] & "/" & $t[2] & "/" & $t[0] & " " & $t[3] & ":" & $t[4] & ":" & $t[5] & @CRLF)
- Return (True)
- EndIf
- Else
- ;No files were found in the folder
- ;ConsoleWrite("No files found in folder " & $Folder & @CRLF)
- Return (False)
- EndIf
- EndFunc ;==>CheckFolderFilesAreUpdating
- Func CheckTCPPortOpen($sCheckTcpHost, $iCheckTcpPort)
- ; Set our connection timeout to whatever the check interval is.
- Opt("TCPTimeout", $intProcessCheckInterval)
- TCPStartup() ; Start the TCP service.
- ; Assign a Local variable the socket and connect to a Listening socket with the IP Address and Port specified.
- Local $iSocket = TCPConnect($sCheckTcpHost, $iCheckTcpPort)
- If @error Then
- ; The server is probably offline/port is not opened on the server.
- ;ConsoleWrite("CheckTCPPortOpen: Could not connect" & @CRLF)
- TCPCloseSocket($iSocket)
- TCPShutdown() ; Close the TCP service.
- Return False
- Else
- ;ConsoleWrite("CheckTCPPortOpen: Connection successful." & @CRLF)
- TCPCloseSocket($iSocket)
- TCPShutdown() ; Close the TCP service.
- Return True
- EndIf
- EndFunc ;==>CheckTCPPortOpen
- ; Hand this function the URL to an MJPEG stream, return true if it's streaming >= 100,000 bytes of data in $intProcessCheckInterval milliseconds
- Func ServiceCheckMjpeg($sCheckUrl)
- Local $hTimer = TimerInit() ; Begin the timer and store the handle in a variable.
- Local $hDownload = InetGet($sCheckUrl, "NUL", $INET_FORCERELOAD, $INET_DOWNLOADBACKGROUND) ; Start a background download
- Do
- Sleep(100)
- ;ConsoleWrite('InetGetInfo($hDownload, $INET_DOWNLOADREAD):' & InetGetInfo($hDownload, $INET_DOWNLOADREAD) & @CRLF)
- If InetGetInfo($hDownload, $INET_DOWNLOADREAD) >= 100000 Then ; if we've got a big enough chunk of data, return true
- InetClose($hDownload)
- Return True
- EndIf
- Until InetGetInfo($hDownload, $INET_DOWNLOADCOMPLETE) Or (TimerDiff($hTimer) > $intProcessCheckInterval) ; if we've run out of time or we completed without enough data, return false
- InetClose($hDownload)
- Return False
- EndFunc ;==>CheckTCPPortOpen
- Func RecordErrorEvent($sEventDesc)
- ; Log exception to Application event log and update the tray icon text
- TraySetToolTip("ERROR @ " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & $sEventDesc)
- ConsoleWrite(@YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " ERROR: " & $sEventDesc & @CRLF)
- Run (@ComSpec & ' /c eventcreate.exe /t WARNING /l Application /SO VLCProcessManager /ID 1 /d "' & $sEventDesc & '"', "", @SW_HIDE)
- EndFunc ;==>RecordErrorEvent
- Func RecordInformationEvent($sEventDesc)
- ; Log exception to Application event log and update the tray icon text
- TraySetToolTip("STATUS @ " & @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & $sEventDesc)
- ConsoleWrite(@YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " STATUS: " & $sEventDesc & @CRLF)
- Run (@ComSpec & ' /c eventcreate.exe /t Information /l Application /SO VLCProcessManager /ID 1 /d "' & $sEventDesc & '"', "", @SW_HIDE)
- EndFunc ;==>RecordInformationEvent
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement