Compare commits
2 Commits
6d408386bc
...
d6644a65f3
| Author | SHA1 | Date | |
|---|---|---|---|
| d6644a65f3 | |||
| 4153efaae9 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -54,3 +54,10 @@ data/
|
||||
captures/
|
||||
/logs/
|
||||
/tests/
|
||||
|
||||
# Diagnostic documents and scripts - DO NOT COMMIT
|
||||
*诊断*.md
|
||||
*分析*.md
|
||||
*报告*.md
|
||||
*修复*.sh
|
||||
*patch*.py
|
||||
|
||||
186
main.py
186
main.py
@@ -98,7 +98,9 @@ class EdgeInferenceService:
|
||||
def _on_config_update(topic, data):
|
||||
if self._algorithm_manager:
|
||||
self._algorithm_manager.reload_all_algorithms()
|
||||
# 配置更新后动态加载新摄像头流
|
||||
# 配置更新后清理无ROI的摄像头流
|
||||
self._cleanup_cameras_without_roi()
|
||||
# 配置更新后动态加载新摄像头流(有ROI的)
|
||||
self._reload_cameras()
|
||||
self._config_manager.register_callback("config_update", _on_config_update)
|
||||
self._logger.info("配置管理器初始化成功")
|
||||
@@ -264,11 +266,73 @@ class EdgeInferenceService:
|
||||
|
||||
self._logger.info("所有组件初始化完成")
|
||||
|
||||
def _load_cameras(self):
|
||||
"""加载摄像头配置"""
|
||||
cameras = self._config_manager.get_cameras()
|
||||
def _get_camera_ids_with_roi(self) -> set:
|
||||
"""获取有ROI配置的摄像头ID集合
|
||||
|
||||
Returns:
|
||||
set: 有ROI配置的摄像头ID集合
|
||||
"""
|
||||
try:
|
||||
all_rois = self._config_manager.get_roi_configs(force_refresh=True)
|
||||
camera_ids = {roi.camera_id for roi in all_rois if roi.camera_id}
|
||||
return camera_ids
|
||||
except Exception as e:
|
||||
self._logger.error(f"获取ROI配置失败: {e}")
|
||||
return set()
|
||||
|
||||
def _get_camera_config_by_id(self, camera_id: str):
|
||||
"""根据摄像头ID获取配置
|
||||
|
||||
Args:
|
||||
camera_id: 摄像头ID
|
||||
|
||||
Returns:
|
||||
CameraInfoModel or None: 摄像头配置对象,未找到返回None
|
||||
"""
|
||||
try:
|
||||
cameras = self._config_manager.get_cameras()
|
||||
for camera in cameras:
|
||||
if camera.camera_id == camera_id:
|
||||
return camera
|
||||
return None
|
||||
except Exception as e:
|
||||
self._logger.error(f"获取摄像头配置失败 {camera_id}: {e}")
|
||||
return None
|
||||
|
||||
def _load_cameras(self):
|
||||
"""加载摄像头配置 - 只启动有ROI配置的摄像头
|
||||
|
||||
逻辑:
|
||||
1. 获取所有ROI配置,提取关联的摄像头ID
|
||||
2. 只为有ROI配置的摄像头启动视频流
|
||||
3. 避免启动无用的视频流,节省资源
|
||||
"""
|
||||
# 获取有ROI配置的摄像头ID
|
||||
camera_ids_with_roi = self._get_camera_ids_with_roi()
|
||||
|
||||
if not camera_ids_with_roi:
|
||||
self._logger.warning("未找到任何ROI配置,不启动视频流")
|
||||
return
|
||||
|
||||
self._logger.info(f"检测到 {len(camera_ids_with_roi)} 个摄像头有ROI配置")
|
||||
|
||||
# 只启动有ROI的摄像头
|
||||
success_count = 0
|
||||
failed_count = 0
|
||||
|
||||
for camera_id in camera_ids_with_roi:
|
||||
camera = self._get_camera_config_by_id(camera_id)
|
||||
|
||||
if not camera:
|
||||
self._logger.warning(f"摄像头 {camera_id} 有ROI但未找到配置,跳过")
|
||||
failed_count += 1
|
||||
continue
|
||||
|
||||
if not camera.rtsp_url:
|
||||
self._logger.warning(f"摄像头 {camera_id} 缺少 rtsp_url,跳过")
|
||||
failed_count += 1
|
||||
continue
|
||||
|
||||
for camera in cameras:
|
||||
try:
|
||||
self._stream_manager.add_stream(
|
||||
camera_id=camera.camera_id,
|
||||
@@ -277,23 +341,64 @@ class EdgeInferenceService:
|
||||
on_frame_callback=self._create_frame_callback(camera.camera_id)
|
||||
)
|
||||
self._logger.info(f"已添加摄像头: {camera.camera_id}")
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
self._logger.error(f"添加摄像头失败 {camera.camera_id}: {e}")
|
||||
failed_count += 1
|
||||
|
||||
self._logger.info(
|
||||
f"摄像头加载完成 - 成功: {success_count}, 失败: {failed_count}, "
|
||||
f"总计: {len(camera_ids_with_roi)}"
|
||||
)
|
||||
|
||||
def _reload_cameras(self):
|
||||
"""配置更新后动态加载新摄像头(不重复添加已有的)"""
|
||||
"""配置更新后动态加载新摄像头 - 只添加有ROI配置且未启动的摄像头
|
||||
|
||||
逻辑:
|
||||
1. 获取当前有ROI配置的摄像头ID
|
||||
2. 过滤出尚未启动的摄像头
|
||||
3. 动态添加并启动新摄像头流
|
||||
"""
|
||||
if not self._stream_manager or not self._config_manager:
|
||||
return
|
||||
|
||||
try:
|
||||
cameras = self._config_manager.get_cameras(force_refresh=True)
|
||||
existing = set(self._stream_manager._streams.keys())
|
||||
added = 0
|
||||
for camera in cameras:
|
||||
if camera.camera_id in existing:
|
||||
# 获取有ROI配置的摄像头ID
|
||||
camera_ids_with_roi = self._get_camera_ids_with_roi()
|
||||
|
||||
if not camera_ids_with_roi:
|
||||
self._logger.debug("配置更新后未找到有ROI配置的摄像头")
|
||||
return
|
||||
|
||||
# 获取已启动的摄像头
|
||||
existing_streams = set(self._stream_manager._streams.keys())
|
||||
|
||||
# 找出需要新增的摄像头(有ROI但未启动)
|
||||
new_camera_ids = camera_ids_with_roi - existing_streams
|
||||
|
||||
if not new_camera_ids:
|
||||
self._logger.debug("配置更新后无需新增摄像头流")
|
||||
return
|
||||
|
||||
self._logger.info(f"检测到 {len(new_camera_ids)} 个新摄像头需要启动")
|
||||
|
||||
# 动态添加新摄像头
|
||||
success_count = 0
|
||||
failed_count = 0
|
||||
|
||||
for camera_id in new_camera_ids:
|
||||
camera = self._get_camera_config_by_id(camera_id)
|
||||
|
||||
if not camera:
|
||||
self._logger.warning(f"摄像头 {camera_id} 有ROI但未找到配置,跳过")
|
||||
failed_count += 1
|
||||
continue
|
||||
|
||||
if not camera.rtsp_url:
|
||||
self._logger.warning(f"摄像头 {camera.camera_id} 无 rtsp_url,跳过")
|
||||
self._logger.warning(f"摄像头 {camera_id} 缺少 rtsp_url,跳过")
|
||||
failed_count += 1
|
||||
continue
|
||||
|
||||
try:
|
||||
self._stream_manager.add_stream(
|
||||
camera_id=camera.camera_id,
|
||||
@@ -301,16 +406,65 @@ class EdgeInferenceService:
|
||||
target_fps=self._settings.video_stream.default_fps,
|
||||
on_frame_callback=self._create_frame_callback(camera.camera_id)
|
||||
)
|
||||
# 立即启动新添加的流
|
||||
self._stream_manager._streams[camera.camera_id].start()
|
||||
added += 1
|
||||
success_count += 1
|
||||
self._logger.info(f"动态添加并启动摄像头: {camera.camera_id}")
|
||||
except Exception as e:
|
||||
self._logger.error(f"动态添加摄像头失败 {camera.camera_id}: {e}")
|
||||
if added > 0:
|
||||
self._logger.info(f"配置更新后新增 {added} 个摄像头流")
|
||||
failed_count += 1
|
||||
|
||||
if success_count > 0:
|
||||
self._logger.info(
|
||||
f"配置更新后新增摄像头完成 - 成功: {success_count}, 失败: {failed_count}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self._logger.error(f"动态加载摄像头失败: {e}")
|
||||
|
||||
|
||||
def _cleanup_cameras_without_roi(self):
|
||||
"""清理没有ROI配置的摄像头视频流
|
||||
|
||||
逻辑:
|
||||
1. 获取当前有ROI配置的摄像头ID
|
||||
2. 找出已启动但没有ROI的摄像头
|
||||
3. 停止并移除这些摄像头的视频流,节省资源
|
||||
"""
|
||||
if not self._stream_manager or not self._config_manager:
|
||||
return
|
||||
|
||||
try:
|
||||
# 获取有ROI配置的摄像头ID
|
||||
camera_ids_with_roi = self._get_camera_ids_with_roi()
|
||||
|
||||
# 获取已启动的摄像头
|
||||
running_streams = set(self._stream_manager._streams.keys())
|
||||
|
||||
# 找出需要停止的摄像头(已启动但没有ROI)
|
||||
cameras_to_remove = running_streams - camera_ids_with_roi
|
||||
|
||||
if not cameras_to_remove:
|
||||
self._logger.debug("无需清理摄像头视频流")
|
||||
return
|
||||
|
||||
self._logger.info(f"检测到 {len(cameras_to_remove)} 个摄像头无ROI配置,需要停止")
|
||||
|
||||
# 停止并移除这些摄像头的视频流
|
||||
removed_count = 0
|
||||
for camera_id in cameras_to_remove:
|
||||
try:
|
||||
self._stream_manager.remove_stream(camera_id)
|
||||
removed_count += 1
|
||||
self._logger.info(f"已停止并移除摄像头流: {camera_id} (无ROI配置)")
|
||||
except Exception as e:
|
||||
self._logger.error(f"移除摄像头流失败 {camera_id}: {e}")
|
||||
|
||||
if removed_count > 0:
|
||||
self._logger.info(f"清理完成 - 已移除 {removed_count} 个无ROI的摄像头流")
|
||||
|
||||
except Exception as e:
|
||||
self._logger.error(f"清理摄像头流失败: {e}")
|
||||
|
||||
def _create_frame_callback(self, camera_id: str):
|
||||
"""创建帧处理回调"""
|
||||
def callback(frame):
|
||||
|
||||
Reference in New Issue
Block a user