bdd5ab30fd
- 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
163 lines
5.0 KiB
PHP
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']);
|
|
}
|