# -*- coding: utf-8 -*- """启动前环境分析:Python 依赖、ffmpeg、Node/npm、端口提示(Linux)。""" from __future__ import annotations import importlib.util import shutil import socket import subprocess import sys def _has_module(name: str) -> bool: return importlib.util.find_spec(name) is not None def _local_ips() -> list[str]: out: list[str] = [] try: hostname = socket.gethostname() for info in socket.getaddrinfo(hostname, None, family=socket.AF_INET): ip = info[4][0] if ip and not ip.startswith("127.") and ip not in out: out.append(ip) except OSError: pass return out[:4] def _node_major() -> tuple[int | None, str | None]: node = shutil.which("node") if not node: return None, None try: raw = subprocess.check_output([node, "-v"], stderr=subprocess.STDOUT, text=True).strip() except Exception: return None, node try: major = int(raw.lstrip("v").split(".", 1)[0]) except Exception: major = None return major, f"{node} ({raw})" def print_env_report( *, dev: bool, need_npm: bool, host: str, port: str, next_port: str = "3000", ) -> None: print() print("┌── 环境检测 ─────────────────────────────────────────") print(f"│ 系统: {sys.platform} Python: {sys.version.split()[0]}") ok = True for mod, label in ( ("fastapi", "FastAPI"), ("uvicorn", "Uvicorn"), ): if _has_module(mod): print(f"│ ✓ {label} 已安装") else: print(f"│ ✕ 缺少 {label},请执行: pip install -r requirements.txt") ok = False ff = shutil.which("ffmpeg") fp = shutil.which("ffplay") if ff: print(f"│ ✓ ffmpeg: {ff}") else: print("│ ⚠ 未找到 ffmpeg(推流/录制/OBS 拉流会失败;Docker 镜像已内置)") ok = False if fp: print(f"│ ✓ ffplay: {fp}") else: print("│ ⚠ 未找到 ffplay(HDMI 全屏播放需要完整 ffmpeg 套件)") if need_npm: major, node_desc = _node_major() npm = shutil.which("npm") docker = shutil.which("docker") if node_desc: if major is not None and major < 18: print(f"│ ⚠ Node: {node_desc}(Next.js 推荐 Node 18+;可自动尝试 Docker 兜底)") else: print(f"│ ✓ Node: {node_desc}") else: print("│ ✕ 未找到 Node.js(Next.js 构建/开发需要 Node 18+ 或 Docker 兜底)") ok = False if npm: print(f"│ ✓ npm: {npm}") else: print("│ ⚠ 未找到 npm(若有 Node 18+ 通常可用;否则请安装完整 Node 或启用 Docker)") if docker: print(f"│ ✓ Docker: {docker}") elif major is None or (major is not None and major < 18): print("│ ⚠ 无 Docker 时,Node 过低会依赖本机升级才能构建前端") print("│") print("│ 同机端口提示(若冲突请在 config/runtime.env 修改 PORT):") print("│ 本控制台 API/Web 使用环境变量 PORT(默认见 launch.py)") print("│ SRS 常见: 1935/1985/8080/10080 等;代理常见: 7890/9090;Chrome 远程: 9222") print("│") print(f"│ 监听: {host}:{port}") if dev: ips = _local_ips() print(f"│ 开发 UI: 0.0.0.0:{next_port}(局域网可用本机 IP 访问)") if ips: print(f"│ 示例: http://{ips[0]}:{next_port}/") else: if host == "0.0.0.0": ips = _local_ips() if ips: print(f"│ 局域网访问示例: http://{ips[0]}:{port}/") else: print("│ 局域网访问: http://<本机IP>:%s/" % port) print("└────────────────────────────────────────────────────") print() if not ok and not dev: print("[env] 存在警告,仍可尝试启动;若运行失败请按上述提示补全依赖。\n")