feat: Add multi-CDN integration for global video delivery
- Create CDN manager with multi-provider support (Bunny, Cloudflare, S3, Backblaze, Wasabi) - Implement automatic CDN upload and failover system - Add multi-quality video support (360p-2160p) - Build quality selector UI with auto-detection - Track CDN bandwidth usage for cost monitoring - Implement cache purging API - Add background CDN upload worker script - Create comprehensive CDN documentation Features: - Multi-CDN support with priority-based failover - BunnyCDN, Cloudflare R2, AWS S3, Backblaze B2, Wasabi integration - Multi-quality delivery (adaptive quality selection) - Auto quality based on connection speed - User preference persistence - Bandwidth tracking per provider - Cache purge API - Cost optimization strategies - Production-ready with error handling
This commit is contained in:
+162
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* CDN API
|
||||
*
|
||||
* GET /api/cdn.php?action=url&video_id=X&quality=720p - Get CDN URL
|
||||
* GET /api/cdn.php?action=qualities&video_id=X - Get available qualities
|
||||
* GET /api/cdn.php?action=bandwidth&days=30 - Get bandwidth usage
|
||||
* POST /api/cdn.php?action=upload - Upload to CDN
|
||||
* POST /api/cdn.php?action=purge - Purge CDN cache
|
||||
*/
|
||||
|
||||
require_once dirname(__DIR__) . '/f_core/config.boot.php';
|
||||
require_once dirname(__DIR__) . '/f_core/f_classes/class.cdn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
session_start();
|
||||
$current_user_id = $_SESSION['user_id'] ?? null;
|
||||
$cdn = new VCDN();
|
||||
|
||||
$action = $_GET['action'] ?? 'url';
|
||||
|
||||
// Public endpoints
|
||||
if ($action === 'url') {
|
||||
$video_id = $_GET['video_id'] ?? null;
|
||||
$quality = $_GET['quality'] ?? 'original';
|
||||
|
||||
if (!$video_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Video ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$url = $cdn->getCDNUrl($video_id, $quality);
|
||||
|
||||
if ($url) {
|
||||
echo json_encode(['success' => true, 'url' => $url]);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'error' => 'Video not found']);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'qualities') {
|
||||
$video_id = $_GET['video_id'] ?? null;
|
||||
|
||||
if (!$video_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Video ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$qualities = $cdn->getAvailableQualities($video_id);
|
||||
echo json_encode(['success' => true, 'qualities' => $qualities]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Authenticated endpoints
|
||||
if (!$current_user_id) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['success' => false, 'error' => 'Authentication required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'bandwidth':
|
||||
$days = intval($_GET['days'] ?? 30);
|
||||
$provider_id = $_GET['provider_id'] ?? null;
|
||||
|
||||
$data = $cdn->getBandwidthUsage($provider_id, $days);
|
||||
echo json_encode(['success' => true, 'data' => $data]);
|
||||
break;
|
||||
|
||||
case 'upload':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
|
||||
$video_id = $input['video_id'] ?? null;
|
||||
$local_path = $input['local_path'] ?? null;
|
||||
$quality = $input['quality'] ?? 'original';
|
||||
|
||||
if (!$video_id || !$local_path) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Video ID and local path required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Verify ownership
|
||||
global $class_database;
|
||||
$sql = "SELECT usr_id FROM db_videofiles WHERE video_id = ?";
|
||||
$result = $class_database->execute($sql, [$video_id]);
|
||||
|
||||
if (!$result || $class_database->rowCount($result) == 0) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'error' => 'Video not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $class_database->fetch($result);
|
||||
|
||||
if ($row['usr_id'] != $current_user_id) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'error' => 'Permission denied']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$success = $cdn->uploadVideo($video_id, $local_path, $quality);
|
||||
|
||||
echo json_encode(['success' => $success]);
|
||||
break;
|
||||
|
||||
case 'purge':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
|
||||
$video_id = $input['video_id'] ?? null;
|
||||
|
||||
if (!$video_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Video ID required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Verify ownership
|
||||
global $class_database;
|
||||
$sql = "SELECT usr_id FROM db_videofiles WHERE video_id = ?";
|
||||
$result = $class_database->execute($sql, [$video_id]);
|
||||
|
||||
if (!$result || $class_database->rowCount($result) == 0) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'error' => 'Video not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $class_database->fetch($result);
|
||||
|
||||
if ($row['usr_id'] != $current_user_id) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['success' => false, 'error' => 'Permission denied']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$cdn->purgeCache($video_id);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
break;
|
||||
|
||||
default:
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid action']);
|
||||
}
|
||||
Reference in New Issue
Block a user