import os import socket def get_local_ip(): """获取本机局域网 IP""" try: # 创建一个UDP套接字 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 连接一个不需要实际存在的外部地址 s.connect(('8.8.8.8', 80)) ip = s.getsockname()[0] except Exception: ip = "127.0.0.1" finally: s.close() return ip class Settings: LOCAL_IP: str = get_local_ip() LOCAL_PORT: int = 7721 BASE_URL: str = f"http://{LOCAL_IP}:{LOCAL_PORT}" # API 核心配置 API_URL: str = "http://100.64.0.8/v1/workflows/run" API_KEY: str = "Bearer app-qR46FHcfLyKz2kb0tiiRfV50" USER_ID: str = "abc-123" # 滑动窗口配置 (可用于长视频的分片处理) CHUNK_SIZE: int = 10000 OVERLAP_SIZE: int = 500 # 静态资源与图片保存目录配置 STATIC_DIR: str = os.path.join(os.getcwd(), "static") FRAMES_DIR: str = os.path.join(STATIC_DIR, "frames") # ========================================== # 视频帧分析算法配置 (Video Analysis Settings) # ========================================== # HuggingFace 语义分割模型路径 (用于识别手和卡片) VIDEO_SEG_MODEL_DIR: str = r"C:\Code\ML\Model\Card_Seg\segformer_card_hand02_safetensors" # 目标时间戳前后的搜索范围 (毫秒) -> 决定了去目标时间戳附近多大范围内寻找最佳帧 VIDEO_SEARCH_BEFORE_MS: int = int(os.getenv("VIDEO_SEARCH_BEFORE_MS", "1000")) # 往前找/毫秒 VIDEO_SEARCH_AFTER_MS: int = int(os.getenv("VIDEO_SEARCH_AFTER_MS", "6000")) # 往后找 # 视频分析时的抽帧率 -> 例如 4.0 代表每秒只分析 4 帧,避免逐帧分析导致性能雪崩 VIDEO_ANALYSIS_FPS: float = float(os.getenv("VIDEO_ANALYSIS_FPS", "4.0")) # 只对综合得分排名前 K 的候选帧进行 OCR 识别 (OCR 比较耗时,没必要每帧都跑) VIDEO_OCR_TOP_K: int = int(os.getenv("VIDEO_OCR_TOP_K", "5")) # 目标停留时间 (秒) -> 用来奖励那些在画面中稳定停留的帧 (排除一闪而过的残影) VIDEO_DWELL_TARGET_SECONDS: float = float(os.getenv("VIDEO_DWELL_TARGET_SECONDS", "1.2")) # 画面中被判定为"有卡"或"有手"的最小面积比例 (过滤掉误识别的零星像素) VIDEO_MIN_CARD_AREA_RATIO: float = float(os.getenv("VIDEO_MIN_CARD_AREA_RATIO", "0.01")) # 卡片占全图 >= 1% VIDEO_MIN_HAND_AREA_RATIO: float = float(os.getenv("VIDEO_MIN_HAND_AREA_RATIO", "0.005")) # 手占全图 >= 0.5% # 分割模型输出的类别 ID VIDEO_CARD_LABEL_ID: int = int(os.getenv("VIDEO_CARD_LABEL_ID", "1")) VIDEO_HAND_LABEL_ID: int = int(os.getenv("VIDEO_HAND_LABEL_ID", "2")) settings = Settings() # 确保图片输出目录存在,避免运行报错 os.makedirs(settings.FRAMES_DIR, exist_ok=True)