| # YouTube Live Streamer - API Guide |
|
|
| ## Architecture |
|
|
| ``` |
| ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ |
| │ Vercel │ ──▶ │ Hugging Face │ ──▶ │ YouTube │ |
| │ (Dashboard) │ API │ (Streaming API) │ RTMP │ (Live Stream) │ |
| └─────────────────┘ └──────────────────┘ └─────────────────┘ |
| │ |
| ▼ |
| ┌──────────────────┐ |
| │ Google Drive │ |
| │ (Videos) │ |
| └──────────────────┘ |
| ``` |
|
|
| ## API Endpoints |
|
|
| ### 1. Get Status |
| ``` |
| GET /api/status |
| ``` |
| **Response:** |
| ```json |
| { |
| "is_running": true, |
| "status": "streaming", |
| "current_video": { |
| "name": "video1.mp4", |
| "id": "drive_file_id", |
| "started_at": "2026-05-07T10:30:00" |
| }, |
| "videos_queue": [ |
| {"id": "id1", "name": "video1.mp4"}, |
| {"id": "id2", "name": "video2.mp4"} |
| ], |
| "videos_played": 5, |
| "session_start": "2026-05-07T10:00:00", |
| "session_end": "2026-05-07T16:00:00", |
| "total_stream_time": 18000, |
| "remaining_time_minutes": 120 |
| } |
| ``` |
|
|
| ### 2. Start Stream |
| ``` |
| POST /api/start |
| ``` |
| **Body:** |
| ```json |
| { |
| "duration_hours": 6.5, |
| "shuffle": true, |
| "youtube_stream_key": "xxxx-xxxx-xxxx" // optional, can use env var |
| } |
| ``` |
| **Response:** |
| ```json |
| { |
| "success": true, |
| "message": "Stream started for 6.5 hours", |
| "duration_hours": 6.5, |
| "shuffle": true |
| } |
| ``` |
|
|
| ### 3. Stop Stream |
| ``` |
| POST /api/stop |
| ``` |
| **Response:** |
| ```json |
| { |
| "success": true, |
| "message": "Stop signal sent. Stream will end after current video." |
| } |
| ``` |
|
|
| ### 4. Get Available Videos |
| ``` |
| GET /api/videos |
| ``` |
| **Response:** |
| ```json |
| { |
| "count": 10, |
| "videos": [ |
| {"id": "drive_id_1", "name": "video1.mp4"}, |
| {"id": "drive_id_2", "name": "video2.mp4"} |
| ] |
| } |
| ``` |
|
|
| ## Environment Variables |
|
|
| | Variable | Required | Default | Description | |
| |----------|----------|---------|-------------| |
| | `YOUTUBE_STREAM_KEY` | Yes | - | YouTube stream key | |
| | `GOOGLE_OAUTH_CLIENT_ID` | Yes | - | Google OAuth client ID | |
| | `GOOGLE_OAUTH_CLIENT_SECRET` | Yes | - | Google OAuth client secret | |
| | `GOOGLE_DRIVE_REFRESH_TOKEN` | Yes | - | Drive refresh token | |
| | `GOOGLE_DRIVE_FOLDER_ID` | Yes | - | Drive folder with videos | |
| | `API_MODE` | No | `true` | Run as API server | |
| | `SESSION_DURATION_HOURS` | No | `6` | Default stream duration | |
| | `SHUFFLE_VIDEOS` | No | `true` | Shuffle video order | |
|
|
| ## Frontend Example (React/Next.js) |
|
|
| ```typescript |
| const API_URL = process.env.NEXT_PUBLIC_STREAMER_API_URL; |
| |
| // Get status |
| const status = await fetch(`${API_URL}/api/status`).then(r => r.json()); |
| |
| // Start stream |
| await fetch(`${API_URL}/api/start`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ duration_hours: 6, shuffle: true }) |
| }); |
| |
| // Stop stream |
| await fetch(`${API_URL}/api/stop`, { method: 'POST' }); |
| ``` |
|
|
| ## Running Locally |
|
|
| ```bash |
| # Install dependencies |
| pip install -r requirements.txt |
| |
| # Set environment variables |
| export YOUTUBE_STREAM_KEY=xxxx |
| export GOOGLE_OAUTH_CLIENT_ID=xxxx |
| export GOOGLE_OAUTH_CLIENT_SECRET=xxxx |
| export GOOGLE_DRIVE_REFRESH_TOKEN=xxxx |
| export GOOGLE_DRIVE_FOLDER_ID=xxxx |
| |
| # Run API server |
| python app.py |
| |
| # Or with explicit env |
| API_MODE=true python app.py |
| ``` |
|
|
| ## Deployment |
|
|
| ### Hugging Face Space |
| 1. Create new Space with Docker SDK |
| 2. Upload this code |
| 3. Set environment variables in Space Settings |
| 4. Space will auto-run API on port 7860 |
|
|
| ### Vercel Frontend |
| 1. Create Next.js app |
| 2. Call HF API endpoints |
| 3. Show live status, current video, queue |
| 4. Add start/stop controls |
|
|
| ## Important Notes |
|
|
| - Stream stops gracefully after current video when `stop` is called |
| - Videos are downloaded to `/tmp` and cleaned up after streaming |
| - Each session shuffles videos (if enabled) for variety |
| - Session auto-stops after `duration_hours` even if videos remain |
|
|