from __future__ import annotations import argparse import sys from .ingress import BrainEventIngress from .runtime import DemoEngine from .server import parse_bind, serve from .source import StreamSource, SyntheticSource, read_stream_url, require_opencv def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="YoVision Brain single-stream engineering prototype") parser.add_argument("--source", choices=("synthetic", "stream"), default="synthetic") parser.add_argument("--stream-url-file", help="absolute external file containing one RTSP URL") parser.add_argument("--bind", default="127.0.0.1:8090", help="loopback bind address") parser.add_argument("--fps", type=float, default=2.0, help="prototype processing FPS (0, 30]") parser.add_argument("--event-ingress-config", help="absolute external Brain-to-Bell ingress configuration") return parser def main(argv: list[str] | None = None) -> int: args = build_parser().parse_args(argv) try: require_opencv() parse_bind(args.bind) if args.source == "stream": if not args.stream_url_file: raise ValueError("--stream-url-file is required for stream mode") source = StreamSource(read_stream_url(args.stream_url_file)) else: if args.stream_url_file: raise ValueError("--stream-url-file is only valid for stream mode") source = SyntheticSource() event_ingress = BrainEventIngress.from_file(args.event_ingress_config) if args.event_ingress_config else None engine = DemoEngine(source, fps=args.fps, event_ingress=event_ingress) except (RuntimeError, ValueError) as exc: print(f"Brain demo configuration error: {exc}", file=sys.stderr) return 2 print(f"Brain demo listening on http://{args.bind}/brain-demo") print("Engineering prototype only; synthetic replay and HOG output are not production model evidence.") try: serve(engine, args.bind) except KeyboardInterrupt: return 0 return 0 if __name__ == "__main__": raise SystemExit(main())