From 04bd6d3e15c15b52ee7f2f7f60b34223ffc29b62 Mon Sep 17 00:00:00 2001 From: zqc <835569504@qq.com> Date: Thu, 26 Feb 2026 15:29:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0main=5Fstart.py=EF=BC=8C?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E6=AD=A4=E5=85=A5=E5=8F=A3=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 7 +++- main_start.py | 70 +++++++++++++++++++++++++++++++++++++++ rtsp_service_ws_kadian.py | 64 +++++++++++++++++++++++++++++++---- 3 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 main_start.py diff --git a/config.yaml b/config.yaml index b221eb0..420fd8d 100644 --- a/config.yaml +++ b/config.yaml @@ -34,4 +34,9 @@ cameras: - id: 1 index: testindexcode name: Entrance - rtsp_url: rtsp://localhost:8554/test + params: + roi_points: + - [0.15, 0.001] + - [0.5, 0.001] + - [1.0, 0.8] + - [0.35, 1.0] diff --git a/main_start.py b/main_start.py new file mode 100644 index 0000000..9641c7a --- /dev/null +++ b/main_start.py @@ -0,0 +1,70 @@ +# main_start.py +# 主启动脚本:读取配置并通过 subprocess 启动 rtsp_service_ws_kadian.py + +import json +import yaml +import base64 +import subprocess +import sys +from typing import List + +from common.camera_config import CameraConfig +from utils.logger import get_logger + +logger = get_logger(__name__) + + +def load_cameras_from_yaml(config_path: str = "config.yaml") -> List[dict]: + """从 YAML 文件加载摄像头配置""" + with open(config_path, "r", encoding="utf-8") as f: + cfg = yaml.safe_load(f) + return cfg.get("cameras", []) + + +def cameras_to_base64_json(cameras: List[dict]) -> str: + """将摄像头配置转换为 base64 编码的 JSON 字符串""" + json_str = json.dumps(cameras, ensure_ascii=False) + return base64.b64encode(json_str.encode('utf-8')).decode('ascii') + + +def start_rtsp_service(cameras_base64: str, script_path: str = "rtsp_service_ws_kadian.py"): + """启动 RTSP 服务子进程""" + cmd = [ + sys.executable, # 当前 Python 解释器路径 + script_path, + "--cameras", cameras_base64 + ] + + logger.info(f"[INFO] Starting RTSP service with command: python {script_path} --cameras ") + + # 使用 Popen 启动子进程,保持运行 + process = subprocess.Popen(cmd) + + return process + + +if __name__ == "__main__": + config_path = "config.yaml" + + # 1. 读取配置 + cameras_data = load_cameras_from_yaml(config_path) + logger.info(f"[INFO] Loaded {len(cameras_data)} cameras from {config_path}") + + if not cameras_data: + logger.error("[ERROR] No cameras found in config, exiting...") + sys.exit(1) + + # 2. 转换为 base64 JSON + cameras_base64 = cameras_to_base64_json(cameras_data) + + # 3. 启动子进程 + process = start_rtsp_service(cameras_base64) + + # 4. 等待子进程结束 + try: + process.wait() + except KeyboardInterrupt: + logger.info("[INFO] Received interrupt, terminating subprocess...") + process.terminate() + process.wait() + logger.info("[INFO] Subprocess terminated") diff --git a/rtsp_service_ws_kadian.py b/rtsp_service_ws_kadian.py index fa06527..4370a94 100644 --- a/rtsp_service_ws_kadian.py +++ b/rtsp_service_ws_kadian.py @@ -5,10 +5,14 @@ import cv2 import os +import sys +import json import time +import argparse import threading import queue import yaml +import base64 from dataclasses import dataclass @@ -171,11 +175,8 @@ class RTSPCaptureWorker(threading.Thread): # ========================= 服务主类 ========================= class RTSPService: - def __init__(self, config_path: str = "config.yaml"): - with open(config_path, "r", encoding="utf-8") as f: - cfg = yaml.safe_load(f) - self.cameras = [CameraConfig(id=c["id"], name=c.get("name", f"cam_{c['id']}"), index = c["index"], params=c.get("params")) - for c in cfg.get("cameras", [])] + def __init__(self, cameras: list[CameraConfig]): + self.cameras = cameras self.stop_event = threading.Event() self.raw_queue = queue.Queue(maxsize=2) @@ -205,8 +206,59 @@ class RTSPService: logger.info("[INFO] Service stopped") +def parse_cameras_from_json(json_str: str) -> list[CameraConfig]: + """从 JSON 字符串解析摄像头配置(支持 base64 编码)""" + try: + # 尝试 base64 解码 + try: + decoded = base64.b64decode(json_str).decode('utf-8') + cameras_data = json.loads(decoded) + except Exception: + # 如果不是 base64,直接解析 JSON + cameras_data = json.loads(json_str) + + return [CameraConfig( + id=c["id"], + name=c.get("name", f"cam_{c['id']}"), + index=c.get("index"), + params=c.get("params") + ) for c in cameras_data] + except Exception as e: + logger.error(f"[ERROR] Failed to parse cameras JSON: {e}") + return [] + + +def parse_cameras_from_yaml(yaml_path: str) -> list[CameraConfig]: + """从 YAML 文件解析摄像头配置""" + with open(yaml_path, "r", encoding="utf-8") as f: + cfg = yaml.safe_load(f) + return [CameraConfig( + id=c["id"], + name=c.get("name", f"cam_{c['id']}"), + index=c.get("index"), + params=c.get("params") + ) for c in cfg.get("cameras", [])] + + if __name__ == "__main__": - service = RTSPService("config.yaml") + parser = argparse.ArgumentParser(description="RTSP Service for Kadian Detection") + parser.add_argument("--cameras", type=str, help="Cameras config in JSON format (or base64 encoded JSON)") + parser.add_argument("--config", type=str, default="config.yaml", help="Path to config YAML file") + args = parser.parse_args() + + # 优先使用命令行传入的 cameras JSON,否则读取配置文件 + if args.cameras: + cameras = parse_cameras_from_json(args.cameras) + logger.info(f"[INFO] Loaded {len(cameras)} cameras from command line argument") + else: + cameras = parse_cameras_from_yaml(args.config) + logger.info(f"[INFO] Loaded {len(cameras)} cameras from config file: {args.config}") + + if not cameras: + logger.error("[ERROR] No cameras configured, exiting...") + sys.exit(1) + + service = RTSPService(cameras) service.start() try: while True: