test_01 / README.md
lljz66's picture
Update README.md
8fef3da verified
---
title: footclip
sdk: docker
emoji: πŸƒ
colorFrom: red
colorTo: blue
---
# ⚽ FootClip AI β€” Football Highlight Generator API
Automatically generates professional highlight reels from full match videos using **YOLOv8** computer vision and **audio crowd-excitement analysis**.
---
## πŸš€ Deploy on Hugging Face Spaces
### Step-by-Step:
1. Go to [huggingface.co/spaces](https://huggingface.co/spaces) β†’ **Create new Space**
2. Choose **Docker** as the SDK
3. Select **T4 GPU** (free tier works, GPU recommended)
4. Upload all 6 files:
- `main.py`
- `pipeline.py`
- `models.py`
- `requirements.txt`
- `Dockerfile`
- `README.md`
5. The Space auto-builds and starts on **port 7860**
6. Your API is live at: `https://<your-username>-<space-name>.hf.space`
---
## πŸ“‘ API Endpoints
### Base URL
```
https://<your-username>-<space-name>.hf.space
```
---
### `GET /api/health`
Check if the server is running.
```bash
curl https://your-space.hf.space/api/health
```
Response:
```json
{"status": "ok", "device": "cuda", "workspace": "/app/workspace"}
```
---
### `POST /api/upload`
Upload a local video file.
```bash
curl -X POST https://your-space.hf.space/api/upload \
-F "file=@match_video.mp4"
```
Response:
```json
{"filename": "a1b2c3d4_match_video.mp4", "path": "/app/workspace/uploads/a1b2c3d4_match_video.mp4"}
```
---
### `POST /api/process`
Start highlight generation.
**With YouTube URL:**
```bash
curl -X POST https://your-space.hf.space/api/process \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://www.youtube.com/watch?v=VIDEO_ID",
"highlight_duration": 10,
"style": "dynamic",
"output_quality": "720p",
"team_home": "Barcelona",
"team_away": "Real Madrid",
"match_date": "2024-10-26",
"fast_mode": false
}'
```
**With uploaded file (use path from /api/upload):**
```bash
curl -X POST https://your-space.hf.space/api/process \
-H "Content-Type: application/json" \
-d '{
"video_url": "/app/workspace/uploads/a1b2c3d4_match_video.mp4",
"highlight_duration": 8,
"style": "goals_only",
"output_quality": "1080p"
}'
```
**Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `video_url` | string | required | YouTube URL, direct URL, or local path |
| `highlight_duration` | int | 10 | Target duration in minutes (3-20) |
| `style` | string | "dynamic" | `dynamic`, `broadcast`, `goals_only`, `tactical` |
| `output_quality` | string | "720p" | `480p`, `720p`, `1080p` |
| `team_home` | string | null | Home team name (for intro card) |
| `team_away` | string | null | Away team name (for intro card) |
| `match_date` | string | null | Match date (for intro card) |
| `fast_mode` | bool | false | Audio-only analysis (~80% quality, no GPU needed) |
| `frame_sample_rate` | int | 5 | Analyze every Nth frame (higher = faster) |
| `pre_buffer` | float | 3.0 | Seconds before each event |
| `post_buffer` | float | 5.0 | Seconds after each event |
Response:
```json
{"job_id": "abc123def456", "status": "queued"}
```
---
### `GET /api/status/{job_id}`
Poll for job progress.
```bash
curl https://your-space.hf.space/api/status/abc123def456
```
Response (processing):
```json
{
"job_id": "abc123def456",
"status": "processing",
"progress": 0.45,
"stage": "cv",
"message": "Running CV analysis (chunk 2/4)...",
"result": null
}
```
Response (done):
```json
{
"job_id": "abc123def456",
"status": "done",
"progress": 1.0,
"stage": "done",
"message": "βœ… Done in 12.3 min β€” 15 clips, 9.5 min highlight",
"result": {
"output_path": "/app/workspace/output/abc123def456.mp4",
"duration": 570.0,
"clips_count": 15,
"events_detected": 47,
"processing_time": 738.2,
"fast_mode": false,
"goals_detected": 0
}
}
```
---
### `GET /api/download/{job_id}`
Download the final highlight MP4.
```bash
curl -O https://your-space.hf.space/api/download/abc123def456
```
---
### `GET /api/jobs`
List all jobs.
```bash
curl https://your-space.hf.space/api/jobs
```
---
## πŸ”„ Full Workflow Example (Python)
```python
import requests
import time
BASE = "https://your-space.hf.space"
# 1. Start processing
resp = requests.post(f"{BASE}/api/process", json={
"video_url": "https://www.youtube.com/watch?v=VIDEO_ID",
"highlight_duration": 10,
"style": "dynamic",
"output_quality": "720p",
"team_home": "Barcelona",
"team_away": "Real Madrid",
})
job_id = resp.json()["job_id"]
print(f"Job started: {job_id}")
# 2. Poll status
while True:
status = requests.get(f"{BASE}/api/status/{job_id}").json()
print(f"[{status['progress']:.0%}] {status['stage']}: {status['message']}")
if status["status"] in ("done", "error"):
break
time.sleep(10)
# 3. Download
if status["status"] == "done":
video = requests.get(f"{BASE}/api/download/{job_id}")
with open("highlights.mp4", "wb") as f:
f.write(video.content)
print("βœ… Saved highlights.mp4")
else:
print(f"❌ Error: {status['message']}")
```
---
## ⚑ Styles Explained
| Style | Best For |
|-------|----------|
| **dynamic** | Fast-paced, exciting highlights with crowd reactions |
| **broadcast** | Balanced TV-style highlights |
| **goals_only** | Only the most significant goal-like moments |
| **tactical** | Player formations, set pieces, tactical moments |
---
## πŸ’‘ Tips
- **Fast Mode**: Set `fast_mode: true` for quick results without GPU (audio-only analysis)
- **Large videos**: Auto-compressed if >2GB, auto-chunked if >10 min
- **GPU**: T4 GPU processes ~90 min match in ~15 min. CPU takes 3-5x longer
- The API docs are also available at `https://your-space.hf.space/docs` (Swagger UI)