app.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import json
  2. import logging
  3. import multiprocessing as mp
  4. import os
  5. from logging.handlers import QueueHandler
  6. from typing import Dict, List
  7. import yaml
  8. from playhouse.sqlite_ext import SqliteExtDatabase
  9. from frigate.config import FrigateConfig
  10. from frigate.edgetpu import EdgeTPUProcess
  11. from frigate.events import EventProcessor
  12. from frigate.http import create_app
  13. from frigate.log import log_process, root_configurer
  14. from frigate.models import Event
  15. from frigate.mqtt import create_mqtt_client
  16. from frigate.object_processing import TrackedObjectProcessor
  17. from frigate.video import capture_camera, track_camera
  18. from frigate.watchdog import FrigateWatchdog
  19. logger = logging.getLogger(__name__)
  20. class FrigateApp():
  21. def __init__(self):
  22. self.stop_event = mp.Event()
  23. self.config: FrigateConfig = None
  24. self.detection_queue = mp.Queue()
  25. self.detectors: Dict[str, EdgeTPUProcess] = {}
  26. self.detection_out_events: Dict[str, mp.Event] = {}
  27. self.detection_shms: List[mp.shared_memory.SharedMemory] = []
  28. self.log_queue = mp.Queue()
  29. self.camera_metrics = {}
  30. def init_logger(self):
  31. self.log_process = mp.Process(target=log_process, args=(self.log_queue,), name='log_process')
  32. self.log_process.start()
  33. root_configurer(self.log_queue)
  34. def init_config(self):
  35. config_file = os.environ.get('CONFIG_FILE', '/config/config.yml')
  36. self.config = FrigateConfig(config_file=config_file)
  37. for camera_name in self.config.cameras.keys():
  38. # create camera_metrics
  39. self.camera_metrics[camera_name] = {
  40. 'camera_fps': mp.Value('d', 0.0),
  41. 'skipped_fps': mp.Value('d', 0.0),
  42. 'process_fps': mp.Value('d', 0.0),
  43. 'detection_fps': mp.Value('d', 0.0),
  44. 'detection_frame': mp.Value('d', 0.0),
  45. 'read_start': mp.Value('d', 0.0),
  46. 'ffmpeg_pid': mp.Value('i', 0),
  47. 'frame_queue': mp.Queue(maxsize=2)
  48. }
  49. def init_queues(self):
  50. # Queue for clip processing
  51. self.event_queue = mp.Queue()
  52. # Queue for cameras to push tracked objects to
  53. self.detected_frames_queue = mp.Queue(maxsize=len(self.config.cameras.keys())*2)
  54. def init_database(self):
  55. self.db = SqliteExtDatabase(f"/{os.path.join(self.config.save_clips.clips_dir, 'frigate.db')}")
  56. models = [Event]
  57. self.db.bind(models)
  58. self.db.create_tables(models, safe=True)
  59. def init_web_server(self):
  60. self.flask_app = create_app(self.config, self.db, self.camera_metrics, self.detectors, self.detected_frames_processor)
  61. def init_mqtt(self):
  62. self.mqtt_client = create_mqtt_client(self.config.mqtt)
  63. def start_detectors(self):
  64. for name in self.config.cameras.keys():
  65. self.detection_out_events[name] = mp.Event()
  66. shm_in = mp.shared_memory.SharedMemory(name=name, create=True, size=300*300*3)
  67. shm_out = mp.shared_memory.SharedMemory(name=f"out-{name}", create=True, size=20*6*4)
  68. self.detection_shms.append(shm_in)
  69. self.detection_shms.append(shm_out)
  70. for name, detector in self.config.detectors.items():
  71. if detector.type == 'cpu':
  72. self.detectors[name] = EdgeTPUProcess(name, self.detection_queue, out_events=self.detection_out_events, tf_device='cpu')
  73. if detector.type == 'edgetpu':
  74. self.detectors[name] = EdgeTPUProcess(name, self.detection_queue, out_events=self.detection_out_events, tf_device=detector.device)
  75. def start_detected_frames_processor(self):
  76. self.detected_frames_processor = TrackedObjectProcessor(self.config, self.mqtt_client, self.config.mqtt.topic_prefix,
  77. self.detected_frames_queue, self.event_queue, self.stop_event)
  78. self.detected_frames_processor.start()
  79. def start_camera_processors(self):
  80. for name, config in self.config.cameras.items():
  81. camera_process = mp.Process(target=track_camera, name=f"camera_processor:{name}", args=(name, config,
  82. self.detection_queue, self.detection_out_events[name], self.detected_frames_queue,
  83. self.camera_metrics[name]))
  84. camera_process.daemon = True
  85. self.camera_metrics[name]['process'] = camera_process
  86. camera_process.start()
  87. logger.info(f"Camera processor started for {name}: {camera_process.pid}")
  88. def start_camera_capture_processes(self):
  89. for name, config in self.config.cameras.items():
  90. capture_process = mp.Process(target=capture_camera, name=f"camera_capture:{name}", args=(name, config,
  91. self.camera_metrics[name]))
  92. capture_process.daemon = True
  93. self.camera_metrics[name]['capture_process'] = capture_process
  94. capture_process.start()
  95. logger.info(f"Capture process started for {name}: {capture_process.pid}")
  96. def start_event_processor(self):
  97. self.event_processor = EventProcessor(self.config, self.camera_metrics, self.event_queue, self.stop_event)
  98. self.event_processor.start()
  99. def start_watchdog(self):
  100. self.frigate_watchdog = FrigateWatchdog(self.detectors, self.stop_event)
  101. self.frigate_watchdog.start()
  102. def start(self):
  103. self.init_logger()
  104. # TODO: exit if config doesnt parse
  105. self.init_config()
  106. self.init_queues()
  107. self.init_database()
  108. self.init_mqtt()
  109. self.start_detectors()
  110. self.start_detected_frames_processor()
  111. self.start_camera_processors()
  112. self.start_camera_capture_processes()
  113. self.init_web_server()
  114. self.start_event_processor()
  115. self.start_watchdog()
  116. self.flask_app.run(host='127.0.0.1', port=5001, debug=False)
  117. self.stop()
  118. def stop(self):
  119. logger.info(f"Stopping...")
  120. self.stop_event.set()
  121. self.detected_frames_processor.join()
  122. self.event_processor.join()
  123. self.frigate_watchdog.join()
  124. for detector in self.detectors.values():
  125. detector.stop()
  126. while len(self.detection_shms) > 0:
  127. shm = self.detection_shms.pop()
  128. shm.close()
  129. shm.unlink()