'video/mp4', 'webm' => 'video/webm', 'ogg' => 'video/ogg', 'mov' => 'video/quicktime' ]; $mime_type = $mime_types[$extension] ?? 'video/mp4'; // Gestisci Range Request per supportare seek nel video $start = 0; $end = $file_size - 1; $length = $file_size; if (isset($_SERVER['HTTP_RANGE'])) { $range = $_SERVER['HTTP_RANGE']; if (preg_match('/bytes=(\d+)-(\d*)/', $range, $matches)) { $start = intval($matches[1]); if (!empty($matches[2])) { $end = intval($matches[2]); } $length = $end - $start + 1; http_response_code(206); // Partial Content header("Content-Range: bytes $start-$end/$file_size"); } else { http_response_code(200); } } else { http_response_code(200); } // Pulisci output buffer per evitare corruzione if (ob_get_level()) { ob_end_clean(); } // Invia header header("Content-Type: $mime_type"); header("Accept-Ranges: bytes"); header("Content-Length: $length"); // Header per impedire il download header("Content-Disposition: inline; filename=\"video.{$extension}\""); header("X-Content-Type-Options: nosniff"); // Header di cache per migliorare le performance header("Cache-Control: public, max-age=3600"); header("Pragma: public"); // Disabilita compressione per lo streaming header("Content-Encoding: none"); // Apri e leggi il file $fp = fopen($file, 'rb'); if ($fp === false) { http_response_code(500); exit('Impossibile aprire il file video'); } fseek($fp, $start); // Buffer più grande per migliore performance $buffer = 1024 * 256; // 256KB buffer $bytes_sent = 0; while (!feof($fp) && ($bytes_sent < $length) && connection_status() == 0) { $bytes_to_read = min($buffer, $length - $bytes_sent); $data = fread($fp, $bytes_to_read); if ($data === false) { break; } echo $data; $bytes_sent += strlen($data); // Forza l'invio dei dati al browser if (ob_get_level() > 0) { ob_flush(); } flush(); } fclose($fp); exit;