A FastAPI backend + polished web frontend for real-time object detection using YOLOv8.
- 🖼 Image detection — upload any image, get annotated result with bounding boxes & confidence scores
- 🎞 Video detection — upload a video clip, download fully annotated MP4
- 📡 Live streaming — MJPEG stream with real-time detections from:
- YouTube URLs (via yt-dlp)
- Webcam (index 0)
- Local video files
- Adjustable confidence threshold
- Per-class detection counts + confidence colour coding
pip install -r requirements.txtcd yolo-app
python main.py
# or
uvicorn main:app --host 0.0.0.0 --port 8000Navigate to http://localhost:8000
The YOLOv8-nano model (yolov8n.pt) is downloaded automatically on first run (~6 MB).
| Method | Path | Description |
|---|---|---|
POST |
/detect/image |
Detect objects in an uploaded image |
POST |
/detect/video |
Process a video and return annotated MP4 |
POST |
/stream/start |
Start a live detection stream |
GET |
/stream/mjpeg/{job_id} |
MJPEG stream of annotated frames |
GET |
/stream/detections/{job_id} |
Poll current detections as JSON |
DELETE |
/stream/{job_id} |
Stop a running stream |
GET |
/health |
Health check |
POST /detect/image
file— image file (multipart)conf— confidence threshold (0.0–1.0, default 0.3)
POST /detect/video
file— video file (multipart)conf— confidence thresholdmax_frames— maximum frames to process (default 300)
POST /stream/start
source_type—youtube|webcam|video_fileurl— YouTube URL (when source_type=youtube)file— video file (when source_type=video_file)conf— confidence threshold
[
{ "label": "person", "confidence": 0.923, "bbox": [x1, y1, x2, y2] },
{ "label": "car", "confidence": 0.847, "bbox": [x1, y1, x2, y2] }
]Uses YOLOv8 nano by default (fast, ~6 MB). To switch to a larger model, change MODEL_NAME in main.py:
yolov8n.pt— nano (fastest)yolov8s.pt— smallyolov8m.pt— mediumyolov8l.pt— largeyolov8x.pt— extra-large (most accurate)
Browser
│
├─ POST /detect/image ──► YOLO inference ──► Annotated JPEG response
│
├─ POST /detect/video ──► Frame loop ──► Annotated MP4 download
│
└─ POST /stream/start
│
├─ GET /stream/mjpeg/{id} ──► Multipart MJPEG (browser <img>)
└─ GET /stream/detections/{id} ──► JSON polled every 100ms