""" FastAPI 入口。启动: python -m uvicorn server.main:app --host 0.0.0.0 --port 8000 或在 python/ 目录下: uvicorn server.main:app --host 0.0.0.0 --port 8000 """ from __future__ import annotations from pathlib import Path from fastapi import FastAPI, File, Form, HTTPException, UploadFile from fastapi.responses import JSONResponse, Response from .face_renderer import ( EffectNotFoundError, FaceRenderer, NoFaceError, RendererPaths, ) # 路径相对本文件,避免 cwd 不同时找不到资源 _SERVER_DIR = Path(__file__).resolve().parent _PATHS = RendererPaths( obj_path=_SERVER_DIR / "assets" / "face_picture_3dmax.obj", effects_dir=_SERVER_DIR / "effects", ) app = FastAPI(title="Face SDK Web", version="0.1.0") renderer = FaceRenderer(_PATHS) @app.get("/health") def health() -> dict: return {"ok": True} @app.get("/effects") def list_effects() -> dict: return {"effects": renderer.list_effect_ids()} @app.post("/render") async def render( image: UploadFile = File(...), effect_id: int = Form(...), ) -> Response: image_bytes = await image.read() if not image_bytes: raise HTTPException(status_code=400, detail="empty image") try: png_bytes = renderer.render(image_bytes, effect_id) except NoFaceError: return JSONResponse(status_code=400, content={"error": "no_face"}) except EffectNotFoundError as e: raise HTTPException(status_code=404, detail=str(e)) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) return Response(content=png_bytes, media_type="image/png")