0) { ob_end_clean(); } // Mime types (extend as needed) $ext = strtolower(pathinfo($realFile, PATHINFO_EXTENSION)); $mime = [ 'mp4' => 'video/mp4', 'mkv' => 'video/x-matroska', 'avi' => 'video/x-msvideo', 'mov' => 'video/quicktime', 'wmv' => 'video/x-ms-wmv', 'flv' => 'video/x-flv', 'webm' => 'video/webm', 'm4v' => 'video/x-m4v', 'mp3' => 'audio/mpeg', 'wav' => 'audio/wav', 'ogg' => 'audio/ogg', 'flac' => 'audio/flac', 'm4a' => 'audio/mp4', 'aac' => 'audio/aac', 'wma' => 'audio/x-ms-wma', 'opus' => 'audio/opus', ][$ext] ?? 'application/octet-stream'; $size = filesize($realFile); if ($size === false) { http_response_code(500); echo 'Failed to stat file'; exit; } // Always advertise range support header('Accept-Ranges: bytes'); header('Content-Type: ' . $mime); // Optional caching (fine for local LAN usage) header('Cache-Control: public, max-age=3600'); $rangeHeader = $_SERVER['HTTP_RANGE'] ?? ''; if ($rangeHeader === '') { // Full response header('Content-Length: ' . $size); http_response_code(200); $fp = fopen($realFile, 'rb'); if ($fp === false) { http_response_code(500); echo 'Failed to open file'; exit; } $buf = 1024 * 256; // 256KB chunks (fewer syscalls than 8KB) while (!feof($fp) && !connection_aborted()) { $data = fread($fp, $buf); if ($data === false) break; echo $data; } fclose($fp); exit; } // ---- Range response (single-range only) ---- // Examples: // - bytes=0-999 // - bytes=1000- // - bytes=-500 (suffix range) if (!preg_match('/^bytes=(\d*)-(\d*)$/', trim($rangeHeader), $m)) { http_response_code(416); header("Content-Range: bytes */{$size}"); exit; } $startRaw = $m[1]; $endRaw = $m[2]; if ($startRaw === '' && $endRaw === '') { http_response_code(416); header("Content-Range: bytes */{$size}"); exit; } if ($startRaw === '') { // Suffix range: last N bytes $suffixLen = (int)$endRaw; if ($suffixLen <= 0) { http_response_code(416); header("Content-Range: bytes */{$size}"); exit; } $start = max(0, $size - $suffixLen); $end = $size - 1; } else { $start = (int)$startRaw; $end = ($endRaw === '') ? ($size - 1) : (int)$endRaw; } if ($start < 0 || $end < $start || $end >= $size) { http_response_code(416); header("Content-Range: bytes */{$size}"); exit; } $length = $end - $start + 1; http_response_code(206); header("Content-Range: bytes {$start}-{$end}/{$size}"); header("Content-Length: {$length}"); $fp = fopen($realFile, 'rb'); if ($fp === false) { http_response_code(500); echo 'Failed to open file'; exit; } if (fseek($fp, $start) !== 0) { fclose($fp); http_response_code(500); echo 'Failed to seek'; exit; } $buf = 1024 * 256; $remaining = $length; while ($remaining > 0 && !feof($fp) && !connection_aborted()) { $read = min($buf, $remaining); $data = fread($fp, $read); if ($data === false || $data === '') break; echo $data; $remaining -= strlen($data); } fclose($fp); exit;