CoolFace
Apppublic

htrnguyen/golf-tech-analysis

sourceHugging Faceupdated 8mo agoView on Hugging Face
0likes
api_server.py128 linesDownload Raw Back to root
1import os2import shutil3import uuid4from fastapi import FastAPI, UploadFile, File, HTTPException, Request, BackgroundTasks5from fastapi.responses import FileResponse, HTMLResponse6from fastapi.templating import Jinja2Templates7 8app = FastAPI(title="Golf Tech Analysis API")9 10UPLOAD_DIR = "uploads"11TEMPLATES_DIR = "templates"12os.makedirs(UPLOAD_DIR, exist_ok=True)13os.makedirs(TEMPLATES_DIR, exist_ok=True)14 15# Templates16templates = Jinja2Templates(directory=TEMPLATES_DIR)17 18# Import optimized pipeline19from main import analyze_video_fast20from reengineer import reengineer_video21 22 23@app.get("/")24async def root(request: Request):25    """26    Giao diện upload để test (cho developer).27    """28    return templates.TemplateResponse("index.html", {"request": request})29 30 31@app.post("/")32async def analyze_with_video(33    file: UploadFile = File(...), background_tasks: BackgroundTasks = None34):35    """36    UI endpoint: Phân tích + Tạo video có overlay.37    Trả về video để download.38    """39    job_id = str(uuid.uuid4())40    video_ext = os.path.splitext(file.filename)[1]41    video_path = os.path.join(UPLOAD_DIR, f"{job_id}{video_ext}")42    output_dir = os.path.join("output", job_id)43    os.makedirs(output_dir, exist_ok=True)44 45    try:46        # Lưu video47        with open(video_path, "wb") as buffer:48            shutil.copyfileobj(file.file, buffer)49 50        # Phân tích (lưu vào output/)51        master_json = os.path.join(output_dir, "master_data.json")52        result = analyze_video_fast(53            video_path, production=True, output_file=master_json, output_base="output"54        )55 56        # Tạo video có overlay57        output_video = os.path.join(output_dir, "analyzed_video.mp4")58        reengineer_video(master_json, video_path, output_video, production=True)59 60        # Cleanup video gốc61        if os.path.exists(video_path):62            os.remove(video_path)63 64        # Schedule cleanup after response65        def cleanup():66            try:67                if os.path.exists(output_dir):68                    shutil.rmtree(output_dir, ignore_errors=True)69            except:70                pass71 72        if background_tasks:73            background_tasks.add_task(cleanup)74 75        # Trả về video file76        return FileResponse(77            output_video, media_type="video/mp4", filename=f"golf_analysis_{job_id}.mp4"78        )79 80    except Exception as e:81        if os.path.exists(video_path):82            os.remove(video_path)83        if os.path.exists(output_dir):84            shutil.rmtree(output_dir, ignore_errors=True)85        raise HTTPException(status_code=500, detail=str(e))86 87 88@app.post("/api/analyze")89async def api_analyze(file: UploadFile = File(...)):90    """91    Pure API endpoint: Chỉ trả JSON, không tạo video.92    Dùng cho app/web production.93    """94    job_id = str(uuid.uuid4())95    video_ext = os.path.splitext(file.filename)[1]96    video_path = os.path.join(UPLOAD_DIR, f"{job_id}{video_ext}")97 98    try:99        # Lưu video tạm thời100        with open(video_path, "wb") as buffer:101            shutil.copyfileobj(file.file, buffer)102 103        # Gọi optimized pipeline (KHÔNG tạo video)104        result = analyze_video_fast(video_path, production=True)105 106        # Cleanup107        if os.path.exists(video_path):108            os.remove(video_path)109 110        return result111 112    except Exception as e:113        if os.path.exists(video_path):114            os.remove(video_path)115        raise HTTPException(status_code=500, detail=str(e))116 117 118# Check health (GET, HEAD)119@app.api_route("/api/health", methods=["GET", "HEAD"])120async def health_check():121    return {"status": "ok"}122 123 124if __name__ == "__main__":125    import uvicorn126 127    uvicorn.run(app, host="0.0.0.0", port=7860)128