之前的写法是
为了稳妥起见,现在考虑的是:
代码仅供参考:
import subprocess as sp
import multiprocessing as mp
import time
class Live(object):
'''用于推流。
time: 上一次访问的时间
timeThreshold: 时间阈值,超过2mins下次检测到时会关闭转发
'''
def __init__(self, id, sourceUrl, middleUrl, targetUrl, timeThreshold=120):
# 自行设置
self.id = id
self.sourceUrl = sourceUrl # rtsp://admin:[email protected]:554
self.middleUrl = middleUrl # rtmp://localhost:1935/live/3
self.targetUrl = targetUrl # http://172.18.194.3/live?port=1935&app=live&stream=4
self.time = time.time()
self.timeThreshold = timeThreshold # 默认2mins,如果
def run(self):
print(type(self.id), str(self.id))
print('---开启推流,id={}, source={}, middle={}, target={}'.format(
self.id, self.sourceUrl, self.middleUrl, self.targetUrl))
fps = 30
width = 640
height = 480
# ffmpeg -rtsp_transport tcp -i rtsp://admin:[email protected]:554 -vcodec h264 -f flv -an rtmp://localhost:1935/live/1
command = ['ffmpeg',
'-rtsp_transport',
'tcp',
'-i', self.sourceUrl,
'-vcodec', 'h264',
'-f', 'flv',
'-r', str(fps),
'-s', '{}x{}'.format(width, height),
'-preset', 'ultrafast',
'-an',
self.middleUrl]
self.p = sp.Popen(command)
# self.p = sp.run(command)
print(type(self.p), self.id) # pid在杀死的时候并不准确
def kill(self):
'''杀死子进程
'''
self.p.kill()
def updateTime(self):
'''更新上次访问时间
'''
self.time = time.time()
print('id={}的摄像头更新访问时间{}秒'.format(self.id, self.time))
def checkTime(self, curTime):
'''检查当前时间和上次访问时间是否超过阈值,超过就关闭,并返回false
'''
if curTime - self.time > self.timeThreshold:
print('id={}的摄像头已经超过了最大的阈值{}秒'.format(self.id, self.timeThreshold))
self.kill()
return False
# 仍在运行则为True
return True
class LiveList(object):
def __init__(self):
self.llist = []
def updateList(self, newLive: Live):
flag = 0
for i in range(len(self.llist)-1, -1, -1): # 倒序
live = self.llist[i]
if live.id == newLive.id: # 已加入,就更新最后访问时间
flag = 1
live.updateTime()
print('第{}个摄像头更新time'.format(live.id))
else: # 检查其他的摄像头是否已经超过了最大的阈值threshold
if live.checkTime(time.time()) == False: #超过了,删除
print('第{}个摄像头已经超过了最大的阈值threshold'.format(live.id))
self.llist.pop(i)
if flag == 0: # 还没有加入
if len(newLive.sourceUrl) > 0:
# newLive.run()
self.llist.append(Live(newLive.id, newLive.sourceUrl, newLive.middleUrl, newLive.targetUrl))
print("新加入的摄像头运行,它的id为{}".format(self.llist[-1].id))
self.llist[-1].run()
else:
print('新加入的摄像头没有source和target,它的id为{}'.format(newLive.id))
# 全局变量liveList保存正在转发的摄像头id和进程的pid
liveList = LiveList()
######################LiveList
data_dict = {'device_id': data[0], 'source_camera_url': data[1], 'middle_camera_url': data[2], 'target_camera_url': data[3]}
live = Live(data_dict['device_id'], data_dict['source_camera_url'], data_dict['middle_camera_url'], data_dict['target_camera_url'])
liveList.updateList(live)