Files
Krystie bdd5ab30fd 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
2026-03-30 17:45:23 -07:00

163 lines
5.0 KiB
PHP

<?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']);
}