manage multiple cameras

This commit is contained in:
Blake Blackshear 2021-05-30 09:50:33 -05:00
parent a8df97dc1a
commit 4596ada801

View File

@ -18,9 +18,9 @@ from ws4py.websocket import WebSocket
from frigate.util import SharedMemoryFrameManager from frigate.util import SharedMemoryFrameManager
class FFMpegConverter(object): class FFMpegConverter:
def __init__(self): def __init__(self, in_width, in_height, out_width, out_height, bitrate):
ffmpeg_cmd = "ffmpeg -f rawvideo -pix_fmt yuv420p -video_size 1920x1080 -i pipe: -f mpegts -s 640x360 -codec:v mpeg1video -b:v 1000k -bf 0 pipe:".split( ffmpeg_cmd = f"ffmpeg -f rawvideo -pix_fmt yuv420p -video_size {in_width}x{in_height} -i pipe: -f mpegts -s {out_width}x{out_height} -codec:v mpeg1video -b:v {bitrate} -bf 0 pipe:".split(
" " " "
) )
self.process = sp.Popen( self.process = sp.Popen(
@ -48,8 +48,9 @@ class FFMpegConverter(object):
class BroadcastThread(threading.Thread): class BroadcastThread(threading.Thread):
def __init__(self, converter, websocket_server): def __init__(self, camera, converter, websocket_server):
super(BroadcastThread, self).__init__() super(BroadcastThread, self).__init__()
self.camera = camera
self.converter = converter self.converter = converter
self.websocket_server = websocket_server self.websocket_server = websocket_server
@ -57,7 +58,9 @@ class BroadcastThread(threading.Thread):
while True: while True:
buf = self.converter.read(65536) buf = self.converter.read(65536)
if buf: if buf:
self.websocket_server.manager.broadcast(buf, binary=True) for ws in self.websocket_server.manager:
if ws.environ["PATH_INFO"].endswith(self.camera):
ws.send(buf, binary=True)
elif self.converter.process.poll() is not None: elif self.converter.process.poll() is not None:
break break
@ -89,11 +92,21 @@ def output_frames(config, video_output_queue):
websocket_server.initialize_websockets_manager() websocket_server.initialize_websockets_manager()
websocket_thread = threading.Thread(target=websocket_server.serve_forever) websocket_thread = threading.Thread(target=websocket_server.serve_forever)
converter = FFMpegConverter() converters = {}
broadcast_thread = BroadcastThread(converter, websocket_server) broadcasters = {}
for camera, cam_config in config.cameras.items():
converters[camera] = FFMpegConverter(
cam_config.frame_shape[1], cam_config.frame_shape[0], 640, 320, "1000k"
)
broadcasters[camera] = BroadcastThread(
camera, converters[camera], websocket_server
)
websocket_thread.start() websocket_thread.start()
broadcast_thread.start()
for t in broadcasters.values():
t.start()
while not stop_event.is_set(): while not stop_event.is_set():
try: try:
@ -111,9 +124,12 @@ def output_frames(config, video_output_queue):
frame = frame_manager.get(frame_id, config.cameras[camera].frame_shape_yuv) frame = frame_manager.get(frame_id, config.cameras[camera].frame_shape_yuv)
# send frame to ffmpeg process if websockets are connected # send camera frame to ffmpeg process if websockets are connected
if len(websocket_server.manager) > 0: if any(
converter.write(frame.tobytes()) ws.environ["PATH_INFO"].endswith(camera) for ws in websocket_server.manager
):
# write to the converter for the camera if clients are listening to the specific camera
converters[camera].write(frame.tobytes())
if camera in previous_frames: if camera in previous_frames:
frame_manager.delete(previous_frames[camera]) frame_manager.delete(previous_frames[camera])
@ -133,8 +149,10 @@ def output_frames(config, video_output_queue):
frame = frame_manager.get(frame_id, config.cameras[camera].frame_shape_yuv) frame = frame_manager.get(frame_id, config.cameras[camera].frame_shape_yuv)
frame_manager.delete(frame_id) frame_manager.delete(frame_id)
converter.exit() for c in converters.values():
broadcast_thread.join() c.exit()
for b in broadcasters.values():
b.join()
websocket_server.manager.close_all() websocket_server.manager.close_all()
websocket_server.manager.stop() websocket_server.manager.stop()
websocket_server.manager.join() websocket_server.manager.join()