Here is the script I made for restarting the cameras.. Could alter it so it lets you switch streams etc..
import tkinter as tk from tkinter import * import mysql.connector import subprocess from subprocess import Popen, PIPE, STDOUT, call import threading import re import time top = tk.Tk() t = None # Enable auto restart for individual cameras cam1 = 1 cam2 = 1 cam3 = 1 cam4 = 1 cam5 = 1 # Time of last restart c1lastRestartTime = time.time() c2lastRestartTime = time.time() c3lastRestartTime = time.time() c4lastRestartTime = time.time() c5lastRestartTime = time.time() c2UptimeTotal = 0 c1RecordUptime = 0 c2RecordUptime = 0 c3RecordUptime = 0 c4RecordUptime = 0 c5RecordUptime = 0 # Counts to keep track of how many times cameras restart cam1RestartCount = 1 cam2RestartCount = 1 cam3RestartCount = 1 cam4RestartCount = 1 cam5RestartCount = 1 # Disabled by default, enabled using button autoRestart = 0 def Start1(): global c1lastRestartTime global cam1RestartCount timeNow = time.time() delay = timeNow - c1lastRestartTime print(delay) if delay > 20: c1lastRestartTime = time.time() cam1RestartCount = cam1RestartCount + 1 addRecord(1) Stop1() myUrl='xterm -geometry 80x25+50+20 -fg green -hold -e /home/dell/ffmpeg1 -rtsp_transport tcp -thread_queue_size 5096 -i \"rtsp:// admin:pw@192.168.1.64:554\" -rtbufsize 1000M -f lavfi -f dshow -f alsa -i default -c:a libmp3lame -ab 128k -ar 44100 -c:v copy -f flv \"rtmp:// a.rtmp.youtube.com/live2/xxxxxxxxxxxxxxxx\"' subprocess.Popen(myUrl, shell=True) print("Camera 1 started.") def Start2(): global c2lastRestartTime global cam2RestartCount timeNow = time.time() delay = timeNow - c2lastRestartTime print(delay) if delay > 20: c2lastRestartTime = time.time() cam2RestartCount = cam2RestartCount + 1 addRecord(2) Stop2() myUrl='xterm -geometry 80x25+50+380 -fg green -hold -e /home/dell/ffmpeg2 -rtsp_transport tcp -thread_queue_size 5096 -i \"rtsp:// admin:pw@192.168.1.102:554/VideoInput/1/h264/1\" -f lavfi -f dshow -rtbufsize 500M -f alsa -i default -c:a libmp3lame -ab 128k -ar 44100 -c:v copy -threads 0 -bufsize 512k -f flv \"rtmp:// a.rtmp.youtube.com/live2/xxxxxxxxxxxxxxxxxxx\"' subprocess.Popen(myUrl, shell=True) print("Camera 2 started.") def Start3(): global c3lastRestartTime global cam3RestartCount timeNow = time.time() delay = timeNow - c3lastRestartTime print(delay) if delay > 20: c3lastRestartTime = time.time() cam3RestartCount = cam3RestartCount + 1 addRecord(3) Stop3() myUrl='xterm -geometry 80x25+50+730 -fg green -hold -e /home/dell/ffmpeg3 -rtsp_transport tcp -thread_queue_size 5096 -i \"rtsp:// admin:pw@192.168.1.103:554/VideoInput/1/h264/1\" -f lavfi -f dshow -rtbufsize 500M -f alsa -i default -c:a libmp3lame -ab 128k -ar 44100 -c:v copy -threads 0 -bufsize 512k -f flv \"rtmp:// a.rtmp.youtube.com/live2/xxxxxxxxxxxxxxxxxxxxx\"' subprocess.Popen(myUrl, shell=True) print("Camera 3 started.") def Start4(): global c4lastRestartTime global cam4RestartCount timeNow = time.time() delay = timeNow - c4lastRestartTime print(delay) if delay > 20: c4lastRestartTime = time.time() cam4RestartCount = cam4RestartCount + 1 addRecord(4) Stop4() myUrl='xterm -geometry 80x25+560+20 -fg green -hold -e /home/dell/ffmpeg4 -rtsp_transport tcp -thread_queue_size 5096 -i \"rtsp:// admin:pw@192.168.1.104:554/VideoInput/1/h264/1\" -rtbufsize 500M -f lavfi -f dshow -f alsa -i default -c:a libmp3lame -ab 128k -ar 44100 -c:v copy -f flv \"rtmp://a.rtmp.youtube.com/live2/xxxxxxxxxxxxxxxxxxxxxx\"' subprocess.Popen(myUrl, shell=True) print("Camera 4 started.") def Start5(): global c5lastRestartTime global cam5RestartCount timeNow = time.time() delay = timeNow - c5lastRestartTime print(delay) if delay > 20: c5lastRestartTime = time.time() cam5RestartCount = cam5RestartCount + 1 addRecord(5) Stop5() myUrl='xterm -geometry 80x25+560+380 -fg green -hold -e /home/dell/ffmpeg5 -rtsp_transport tcp -thread_queue_size 5096 -i \"rtsp:// admin:pw@192.168.1.105:554/VideoInput/1/h264/1\" -f lavfi -f dshow -rtbufsize 500M -f alsa -i default -c:a libmp3lame -ab 128k -ar 44100 -c:v copy -bufsize 512k -f flv \"rtmp:// a.rtmp.youtube.com/live2/xxxxxxxxxxxxxxxxxxxxxx\"' subprocess.Popen(myUrl, shell=True) print("Camera 5 started.") def addRecord(camNum): mydb = mysql.connector.connect( host="localhost", user="xxx", passwd="xxx", database="cameras" ) mycursor = mydb.cursor() t = time.time() sql = "INSERT INTO test2 (cid, tstamp) VALUES (%s, %s)" val = (camNum, t) mycursor.execute(sql, val) mydb.commit() def StartAll(): Start1() Start2() Start3() Start4() Start5() def ListProcesses(): print("\n-----------------\nFFMpeg Processes: \n") call("ps -A | grep ffmpeg", shell=True) def Stop1(): call("ps -ef | grep ffmpeg1 | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("Camera 1 stopped.") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def Stop2(): call("ps -ef | grep ffmpeg2 | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("Camera 2 stopped.") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def Stop3(): call("ps -ef | grep ffmpeg3 | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("Camera 3 stopped.") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def Stop4(): call("ps -ef | grep ffmpeg4 | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("Camera 4 stopped.") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def Stop5(): call("ps -ef | grep ffmpeg5 | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("Camera 5 stopped.") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def StopAll(): call("ps -ef | grep ffmpeg | grep -v grep | awk '{print $2}' | xargs -r kill -9", shell=True) print("All cameras stopped.\n") #call("ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9", shell=True) def getUptime(camNum): global c1lastRestartTime global c2lastRestartTime global c3lastRestartTime global c4lastRestartTime global c5lastRestartTime global c1RecordUptime global c2RecordUptime global c3RecordUptime global c4RecordUptime global c5RecordUptime currentTime = time.time() if camNum == 1: compareTime = c1lastRestartTime upTime = currentTime - compareTime upTime = int(upTime) if upTime > c1RecordUptime: c1RecordUptime = upTime if camNum == 2: compareTime = c2lastRestartTime upTime = currentTime - compareTime upTime = int(upTime) if upTime > c2RecordUptime: c2RecordUptime = upTime if camNum == 3: compareTime = c3lastRestartTime upTime = currentTime - compareTime upTime = int(upTime) if upTime > c3RecordUptime: c3RecordUptime = upTime if camNum == 4: compareTime = c4lastRestartTime upTime = currentTime - compareTime upTime = int(upTime) if upTime > c4RecordUptime: c4RecordUptime = upTime if camNum == 5: compareTime = c5lastRestartTime upTime = currentTime - compareTime upTime = int(upTime) if upTime > c5RecordUptime: c5RecordUptime = upTime return upTime def check(): global t global cam1 global cam2 global cam3 global cam4 global cam5 global autoRestart global c1RecordUptime global c2RecordUptime global c3RecordUptime global c4RecordUptime global c5RecordUptime X_list = [] Y_list = [] cam1sum=0 cam1avg=0 cam1instances=0 cam2sum=0 cam2avg=0 cam2instances=0 cam3sum=0 cam3avg=0 cam3instances=0 cam4sum=0 cam4avg=0 cam4instances=0 cam5sum=0 cam5avg=0 cam5instances=0 totalUploadAvg=0 call("timeout 5 sysdig -c topprocs_net > camstatus1.txt", shell=True) with open("/home/dell/camstatus1.txt") as catalog: for line in catalog: goodletters = ('1','2','3','4','5','6','7','8','9') if line.startswith(goodletters): column = line.split() x = str(column[0]) y = str(column[1]) x = x[:3] z = y[:6] x = re.sub("[^0-9]", "", x) if z == 'ffmpeg': xfloat = float(x) xint = int(xfloat) X_list.append(xint) y = y[:7] Y_list.append(y) if y == 'ffmpeg1': cam1sum = cam1sum + xint cam1instances = cam1instances + 1 if y == 'ffmpeg2': cam2sum = cam2sum + xint cam2instances = cam2instances + 1 if y == 'ffmpeg3': cam3sum = cam3sum + xint cam3instances = cam3instances + 1 if y == 'ffmpeg4': cam4sum = cam4sum + xint cam4instances = cam4instances + 1 if y == 'ffmpeg5': cam5sum = cam5sum + xint cam5instances = cam5instances + 1 if cam1instances != 0: cam1avg = (cam1sum / cam1instances) * 8 if cam2instances != 0: cam2avg = (cam2sum / cam2instances) * 8 if cam3instances != 0: cam3avg = (cam3sum / cam3instances) * 8 if cam4instances != 0: cam4avg = (cam4sum / cam4instances) * 8 if cam5instances != 0: cam5avg = (cam5sum / cam5instances) * 8 totalUploadAvg = cam1avg + cam2avg + cam3avg + cam4avg + cam5avg print("Instances in file") print(cam1instances) print(cam2instances) print(cam3instances) print(cam4instances) print(cam5instances) c2uptimeavg = c2UptimeTotal / cam2RestartCount print("Camera 1 - Avg Speed: ",cam1avg," Uptime: ",getUptime(1)," Restarts: ",cam1RestartCount,"Record Uptime: ",c1RecordUptime) print("Camera 2 - Avg Speed: ",cam2avg," Uptime: ",getUptime(2)," Restarts: ",cam2RestartCount,"Record Uptime: ",c2RecordUptime) print("Camera 3 - Avg Speed: ",cam3avg," Uptime: ",getUptime(3)," Restarts: ",cam3RestartCount,"Record Uptime: ",c3RecordUptime) print("Camera 4 - Avg Speed: ",cam4avg," Uptime: ",getUptime(4)," Restarts: ",cam4RestartCount,"Record Uptime: ",c4RecordUptime) print("Camera 5 - Avg Speed: ",cam5avg," Uptime: ",getUptime(5)," Restarts: ",cam5RestartCount,"Record Uptime: ",c5RecordUptime) print(" Total UL: ",totalUploadAvg) if autoRestart == 1: if cam1 == 1: if cam1avg < 50 or cam1instances == 0: Start1() if cam2 == 1: if cam2avg < 50 or cam2instances == 0: Start2() if cam3 == 1: if cam3avg < 50 or cam3instances == 0: Start3() if cam4 == 1: if cam4avg < 50 or cam4instances == 0: Start4() if cam5 == 1: if cam5avg < 50 or cam5instances == 0: Start5() t = threading.Timer(10, check) t.start() check() def AutoRestartOn(): global autoRestart t = threading.Timer(5, check) t.start() autoRestart = 1 print("Auto restart ON") def AutoRestartOff(): global autoRestart t.cancel() autoRestart = 0 print("Auto restart OFF") B = tk.Button(top, text ="Cam 1 Start", command = Start1) B.pack() B = tk.Button(top, text ="Cam 2 Start", command = Start2) B.pack() B = tk.Button(top, text ="Cam 3 Start", command = Start3) B.pack() B = tk.Button(top, text ="Cam 4 Start", command = Start4) B.pack() B = tk.Button(top, text ="Cam 5 Start", command = Start5) B.pack() B = tk.Button(top, text ="Cam 1 Stop", command = Stop1) B.pack() B = tk.Button(top, text ="Cam 2 Stop", command = Stop2) B.pack() B = tk.Button(top, text ="Cam 3 Stop", command = Stop3) B.pack() B = tk.Button(top, text ="Cam 4 Stop", command = Stop4) B.pack() B = tk.Button(top, text ="Cam 5 Stop", command = Stop5) B.pack() B = tk.Button(top, text ="Start All", command = StartAll) B.pack() B = tk.Button(top, text ="Stop All", command = StopAll) B.pack() B = tk.Button(top, text ="List Processes", command = ListProcesses) B.pack() B = tk.Button(top, text ="Auto Restart Off", command = AutoRestartOff) B.pack() B = tk.Button(top, text ="Auto Restart On", command = AutoRestartOn) B.pack() top.mainloop() On Sun, Mar 31, 2019 at 5:55 PM Michael Shaffer <mikeshaf...@gmail.com> wrote: > Hmm I don't know. My python script basically just runs ffmpeg in a shell. > It uses nethogs (in Ubunu) to measure how much bandwidth ffmpeg is using. > If it drops below a certain level the script restarts the ffmpeg process. I > also have different buttons for manually starting and stopping each of the > 5 camera streams. Plus turning the auto-restart on and off. > > It wouldn't be hard at all to make a script that would let you switch > which input stream to use for the destination. The ffmpeg process would > restart though so there would be a very short interruption in the sending > to the destination rtmp address. > > Basically I'm using python to manage ffmpeg sessions. I"m not using a rtmp > library in python. I don't know if there is one. > > On Sun, Mar 31, 2019 at 2:47 AM qw <applema...@163.com> wrote: > >> Hi, >> >> >> Does python's rtmp lib support switch two input rtmp streams, and relay >> one of them to destination rtmp address? >> >> >> Thanks! >> >> >> Regards >> >> >> Andrew >> >> >> >> At 2019-03-31 00:09:17, "Michael Shaffer" <mikeshaf...@gmail.com> wrote: >> >I haven't used Nginx but I think it does rtmp relay. I used a python >> script >> >for relaying from my ip cameras to youtube.. >> > >> >On Sat, Mar 30, 2019 at 12:08 PM Michael Shaffer <mikeshaf...@gmail.com> >> >wrote: >> > >> >> Nginx >> >> >> >> On Sat, Mar 30, 2019 at 12:05 PM qw <applema...@163.com> wrote: >> >> >> >>> Hi, >> >>> >> >>> >> >>> Is there some active popular rtmp server that can relay rtmp stream? >> >>> >> >>> >> >>> >> >>> Thanks! >> >>> >> >>> >> >>> Regards >> >>> >> >>> >> >>> Andrew >> >>> >> >>> >> >>> >> >>> >> >>> At 2019-03-30 23:52:45, "Michael Shaffer" <mikeshaf...@gmail.com> >> wrote: >> >>> >I don't think so. I think you have to use an older version of >> ffmpeg. I >> >>> >could never get ffserver to work right.. >> >>> > >> >>> >On Sat, Mar 30, 2019 at 11:49 AM qw <applema...@163.com> wrote: >> >>> > >> >>> >> Hi, >> >>> >> >> >>> >> >> >>> >> does ffmpeg 4 still support ffserver? >> >>> >> >> >>> >> >> >>> >> >> >>> >> Regards >> >>> >> >> >>> >> >> >>> >> Andrew >> >>> >> _______________________________________________ >> >>> >> ffmpeg-user mailing list >> >>> >> ffmpeg-user@ffmpeg.org >> >>> >> https://ffmpeg.org/mailman/listinfo/ffmpeg-user >> >>> >> >> >>> >> To unsubscribe, visit link above, or email >> >>> >> ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". >> >>> >_______________________________________________ >> >>> >ffmpeg-user mailing list >> >>> >ffmpeg-user@ffmpeg.org >> >>> >https://ffmpeg.org/mailman/listinfo/ffmpeg-user >> >>> > >> >>> >To unsubscribe, visit link above, or email >> >>> >ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". >> >>> _______________________________________________ >> >>> ffmpeg-user mailing list >> >>> ffmpeg-user@ffmpeg.org >> >>> https://ffmpeg.org/mailman/listinfo/ffmpeg-user >> >>> >> >>> To unsubscribe, visit link above, or email >> >>> ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". >> >> >> >> >> >_______________________________________________ >> >ffmpeg-user mailing list >> >ffmpeg-user@ffmpeg.org >> >https://ffmpeg.org/mailman/listinfo/ffmpeg-user >> > >> >To unsubscribe, visit link above, or email >> >ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". >> _______________________________________________ >> ffmpeg-user mailing list >> ffmpeg-user@ffmpeg.org >> https://ffmpeg.org/mailman/listinfo/ffmpeg-user >> >> To unsubscribe, visit link above, or email >> ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". > > _______________________________________________ ffmpeg-user mailing list ffmpeg-user@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-user To unsubscribe, visit link above, or email ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe".