Spaces:
Sleeping
Sleeping
| PoolCoach — Hugging Face Spaces (Docker SDK) / VPS. | |
| HF tự build trên server của họ khi push — máy local KHÔNG cần Docker. | |
| Chi tiết: Documents/PoolCoach_Deploy_HFSpaces.md (repo poolcoach-docs). | |
| # 14/08/2026 (BRIEF việc B): image này giờ chạy **Analyzer** (video → danh | |
| sách cú), không chỉ app gợi ý như bản 23/07. Ba thay đổi lớn, mỗi cái có | |
| lý do đứng riêng: | |
| # 1. torch CPU + ultralytics + cv2 QUAY LẠI image (bản 23/07 đã gỡ vì engine | |
| ZonePlanner V2 không nạp net). Analyzer thì cần: detector bàn/bi, ShotNet | |
| c4b, decode video. Bản CPU lấy từ index pytorch riêng — bản PyPI là CUDA | |
| ~2.5GB cho một Space không có GPU. | |
| 2. MỘT tiến trình, không Redis, không worker rời: `POOLCOACH_LOCAL_CV=1` | |
| bật mode "local" (app/jobqueue.py) — transport fakeredis trong tiến | |
| trình + một LUỒNG gọi đúng hàm của scripts/cv_worker.py (app/localcv.py). | |
| Space free là một container; nuôi Redis + 2 worker ở đó là ba tiến | |
| trình và hai lần JIT pooltool trên 2 vCPU. | |
| 3. Ghi ở đâu: HF chạy container bằng uid 1000, /code là read-only với nó. | |
| Mọi thứ CẦN GHI phải ra /tmp — cache numba/mpl/ultralytics VÀ thư mục | |
| kết quả Analyzer (POOLCOACH_ANALYZER_DIR). Thiếu là app chết lúc | |
| runtime chứ không phải lúc build. | |
| FROM python:3.12-slim | |
| WORKDIR /code | |
| uid 1000 phải CÓ TRONG /etc/passwd, không chỉ "được ghi ở đâu đó". | |
| Đo được 14/08 khi chạy thử image bằng `docker run --user 1000:1000`: | |
| luồng CV chết ngay lúc nạp model với `KeyError: getpwuid(): uid not | |
| found: 1000` — thư viện (ultralytics/torch) hỏi HOME qua pwd, mà uid 1000 | |
| không có entry thì ném KeyError chứ không fallback. App vẫn sống (luồng | |
| nhúng tự bắt lỗi) nhưng tab Analyzer chết câm trên Space. `-m` để | |
| /home/user tồn tại và thuộc uid 1000. | |
| RUN useradd -m -u 1000 user | |
| ffmpeg : cắt clip per cú (cv_worker.cut_clip) + ffprobe đo thời lượng | |
| lúc upload (app/main.py). Thiếu ffmpeg thì mọi cú thành | |
| "ffmpeg không cắt được clip" — hỏng đúng tính năng chính. | |
| libgl1 + libglib2.0-0 : opencv-python (bản không headless) cần libGL.so.1 | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| ffmpeg libgl1 libglib2.0-0 \ | |
| && rm -rf /var/lib/apt/lists/* | |
| RUN pip install --no-cache-dir uv | |
| torch CPU ở bước RIÊNG với --index-url CHỈ trỏ index CPU của pytorch — | |
| không được trộn với PyPI ở bước này, nếu không resolver có quyền chọn bản | |
| CUDA. Bước sau pin lại đúng hai phiên bản này (requirements-cv-cpu.txt) để | |
| ultralytics không kéo torch khác đè lên. | |
| RUN uv pip install --system --index-url https://download.pytorch.org/whl/cpu \ | |
| torch==2.12.1 torchvision==0.27.1 | |
| deps trước để tận dụng layer cache (requirements.txt đã chứa | |
| --extra-index-url archive.panda3d.org cho panda3d 1.11 dev) | |
| COPY requirements.txt requirements-app.txt requirements-cv-cpu.txt ./ | |
| RUN uv pip install --system --index-strategy unsafe-best-match \ | |
| -r requirements.txt -r requirements-app.txt -r requirements-cv-cpu.txt | |
| COPY src ./src | |
| COPY app ./app | |
| CHỈ file worker, không cả scripts/ (train/eval/diag không thuộc image). | |
| Mode "local" nạp nó bằng đường dẫn — xem app/localcv.py. | |
| COPY scripts/cv_worker.py ./scripts/cv_worker.py | |
| Đúng HAI model, đích danh: detector bàn/bi + ShotNet c4b đang chạy app. | |
| Cả models/ còn lại (mấy chục run RL/CV cũ) KHÔNG vào image. | |
| COPY models/cv_full_20260805/best.pt ./models/cv_full_20260805/best.pt | |
| COPY models/shotnet_20260812_c4b/best.pt ./models/shotnet_20260812_c4b/best.pt | |
| HF Spaces chạy container bằng uid 1000 (không ghi được /code): | |
| trỏ mọi cache/config VÀ thư mục kết quả Analyzer về /tmp. | |
| ENV HOME=/tmp \ | |
| NUMBA_CACHE_DIR=/tmp/numba \ | |
| MPLCONFIGDIR=/tmp/mpl \ | |
| YOLO_CONFIG_DIR=/tmp \ | |
| PYTHONUNBUFFERED=1 \ | |
| POOLCOACH_LOCAL_CV=1 \ | |
| POOLCOACH_CV_DEVICE=cpu \ | |
| POOLCOACH_ANALYZER_DIR=/tmp/analyzer | |
| EXPOSE 7860 | |
| Chạy bằng chính uid HF sẽ dùng — để `docker run` trên máy giống Space, | |
| không phải phát hiện lỗi quyền sau khi đã push (bài học ngay ở trên). | |
| USER user | |
| CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"] | |