--- 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://-.hf.space` --- ## 📡 API Endpoints ### Base URL ``` https://-.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)