metadata
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:
- Go to huggingface.co/spaces β Create new Space
- Choose Docker as the SDK
- Select T4 GPU (free tier works, GPU recommended)
- Upload all 6 files:
main.pypipeline.pymodels.pyrequirements.txtDockerfileREADME.md
- The Space auto-builds and starts on port 7860
- 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.
curl https://your-space.hf.space/api/health
Response:
{"status": "ok", "device": "cuda", "workspace": "/app/workspace"}
POST /api/upload
Upload a local video file.
curl -X POST https://your-space.hf.space/api/upload \
-F "file=@match_video.mp4"
Response:
{"filename": "a1b2c3d4_match_video.mp4", "path": "/app/workspace/uploads/a1b2c3d4_match_video.mp4"}
POST /api/process
Start highlight generation.
With YouTube URL:
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):
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:
{"job_id": "abc123def456", "status": "queued"}
GET /api/status/{job_id}
Poll for job progress.
curl https://your-space.hf.space/api/status/abc123def456
Response (processing):
{
"job_id": "abc123def456",
"status": "processing",
"progress": 0.45,
"stage": "cv",
"message": "Running CV analysis (chunk 2/4)...",
"result": null
}
Response (done):
{
"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.
curl -O https://your-space.hf.space/api/download/abc123def456
GET /api/jobs
List all jobs.
curl https://your-space.hf.space/api/jobs
π Full Workflow Example (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: truefor 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)