forked from jsl/video_editing_poc
Add runnable local CV model worker
This commit is contained in:
parent
82e557905e
commit
9dc720b0cc
|
|
@ -41,15 +41,23 @@ VIDEO_EDITING_VISUAL_ANALYSIS_FALLBACK_TO_HEURISTIC=true
|
||||||
This repository includes an optional starter worker:
|
This repository includes an optional starter worker:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 -m venv .venv-local-cv
|
tools/run_local_cv_worker.sh
|
||||||
. .venv-local-cv/bin/activate
|
```
|
||||||
pip install fastapi uvicorn opencv-python
|
|
||||||
|
|
||||||
# Optional YOLO object detection:
|
The starter worker installs `tools/local_cv_requirements.txt` into `.venv-local-cv`.
|
||||||
pip install ultralytics
|
It uses OpenCV for blur, exposure, and face-presence signals. It uses YOLO through `ultralytics` for object detection.
|
||||||
export LOCAL_CV_YOLO_MODEL=yolov8n.pt
|
|
||||||
|
|
||||||
uvicorn tools.local_cv_worker:app --host 127.0.0.1 --port 8091
|
Default model behavior:
|
||||||
|
|
||||||
|
- `LOCAL_CV_YOLO_MODEL` defaults to `yolov8n.pt`.
|
||||||
|
- Ultralytics downloads/caches `yolov8n.pt` on first use if it is not already present.
|
||||||
|
- Set `LOCAL_CV_YOLO_MODEL=/absolute/path/to/model.pt` to use local weights.
|
||||||
|
- Set `LOCAL_CV_DISABLE_YOLO=true` to run only OpenCV-based analysis.
|
||||||
|
|
||||||
|
Health check:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://127.0.0.1:8091/health
|
||||||
```
|
```
|
||||||
|
|
||||||
## Worker Request Contract
|
## Worker Request Contract
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ video-clipping:
|
||||||
luts-folder: ${VIDEO_EDITING_ASSETS_LUTS_FOLDER:./input/highlights/assets/luts}
|
luts-folder: ${VIDEO_EDITING_ASSETS_LUTS_FOLDER:./input/highlights/assets/luts}
|
||||||
voiceover-folder: ${VIDEO_EDITING_ASSETS_VOICEOVER_FOLDER:./output/highlight-projects/_voiceover-cache}
|
voiceover-folder: ${VIDEO_EDITING_ASSETS_VOICEOVER_FOLDER:./output/highlight-projects/_voiceover-cache}
|
||||||
visual-analysis:
|
visual-analysis:
|
||||||
provider: ${VIDEO_EDITING_VISUAL_ANALYSIS_PROVIDER:heuristic}
|
provider: ${VIDEO_EDITING_VISUAL_ANALYSIS_PROVIDER:local-cv} #local-cv or heuristic
|
||||||
endpoint: ${VIDEO_EDITING_VISUAL_ANALYSIS_ENDPOINT:http://127.0.0.1:8091/v1/analyze-visuals}
|
endpoint: ${VIDEO_EDITING_VISUAL_ANALYSIS_ENDPOINT:http://127.0.0.1:8091/v1/analyze-visuals}
|
||||||
timeout-ms: ${VIDEO_EDITING_VISUAL_ANALYSIS_TIMEOUT_MS:30000}
|
timeout-ms: ${VIDEO_EDITING_VISUAL_ANALYSIS_TIMEOUT_MS:30000}
|
||||||
fallback-to-heuristic: ${VIDEO_EDITING_VISUAL_ANALYSIS_FALLBACK_TO_HEURISTIC:true}
|
fallback-to-heuristic: ${VIDEO_EDITING_VISUAL_ANALYSIS_FALLBACK_TO_HEURISTIC:true}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
fastapi==0.115.6
|
||||||
|
uvicorn[standard]==0.34.0
|
||||||
|
opencv-python==4.10.0.84
|
||||||
|
ultralytics==8.3.57
|
||||||
|
|
@ -2,10 +2,8 @@
|
||||||
"""Optional local CV worker for the Spring visual-analysis provider.
|
"""Optional local CV worker for the Spring visual-analysis provider.
|
||||||
|
|
||||||
Run:
|
Run:
|
||||||
pip install fastapi uvicorn opencv-python
|
pip install -r tools/local_cv_requirements.txt
|
||||||
# Optional object detection:
|
uvicorn tools.local_cv_worker:app --host 127.0.0.1 --port 8091
|
||||||
pip install ultralytics
|
|
||||||
LOCAL_CV_YOLO_MODEL=yolov8n.pt uvicorn tools.local_cv_worker:app --host 127.0.0.1 --port 8091
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
@ -34,6 +32,16 @@ app = FastAPI(title="Local CV Visual Analysis Worker")
|
||||||
_yolo_model: Any | None = None
|
_yolo_model: Any | None = None
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
def health() -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"status": "ok",
|
||||||
|
"opencvAvailable": cv2 is not None,
|
||||||
|
"yoloAvailable": YOLO is not None,
|
||||||
|
"yoloModel": configured_yolo_model(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.post("/v1/analyze-visuals")
|
@app.post("/v1/analyze-visuals")
|
||||||
def analyze_visuals(payload: dict[str, Any]) -> dict[str, Any]:
|
def analyze_visuals(payload: dict[str, Any]) -> dict[str, Any]:
|
||||||
source = payload.get("source", {})
|
source = payload.get("source", {})
|
||||||
|
|
@ -101,7 +109,7 @@ def object_labels(thumbnails: list[str]) -> list[dict[str, Any]]:
|
||||||
|
|
||||||
def yolo_model() -> Any | None:
|
def yolo_model() -> Any | None:
|
||||||
global _yolo_model
|
global _yolo_model
|
||||||
model_path = os.getenv("LOCAL_CV_YOLO_MODEL")
|
model_path = configured_yolo_model()
|
||||||
if YOLO is None or not model_path:
|
if YOLO is None or not model_path:
|
||||||
return None
|
return None
|
||||||
if _yolo_model is None:
|
if _yolo_model is None:
|
||||||
|
|
@ -109,6 +117,12 @@ def yolo_model() -> Any | None:
|
||||||
return _yolo_model
|
return _yolo_model
|
||||||
|
|
||||||
|
|
||||||
|
def configured_yolo_model() -> str:
|
||||||
|
if os.getenv("LOCAL_CV_DISABLE_YOLO", "false").lower() == "true":
|
||||||
|
return ""
|
||||||
|
return os.getenv("LOCAL_CV_YOLO_MODEL", "yolov8n.pt")
|
||||||
|
|
||||||
|
|
||||||
def face_presence(thumbnails: list[str]) -> str:
|
def face_presence(thumbnails: list[str]) -> str:
|
||||||
if cv2 is None or not thumbnails:
|
if cv2 is None or not thumbnails:
|
||||||
return "unknown_without_face_detector"
|
return "unknown_without_face_detector"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HOST="${LOCAL_CV_HOST:-127.0.0.1}"
|
||||||
|
PORT="${LOCAL_CV_PORT:-8091}"
|
||||||
|
|
||||||
|
if [ ! -d ".venv-local-cv" ]; then
|
||||||
|
python3 -m venv .venv-local-cv
|
||||||
|
fi
|
||||||
|
|
||||||
|
. .venv-local-cv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -r tools/local_cv_requirements.txt
|
||||||
|
|
||||||
|
exec uvicorn tools.local_cv_worker:app --host "$HOST" --port "$PORT"
|
||||||
Loading…
Reference in New Issue