I have reviewed several similar codes, I have tried them all, but they all work when the multimedia file is hosted locally, when the multimedia file is in a url it does not work, it does not play the video.
They could suggest what changes should be used for this script to work on both url and local media files.
//$path = 'video.mp4'; $path = 'https://ia601407.us.archive.org/5/items/205_20210726/205.mp4'; $file = $path; $fp = @fopen($file, 'rb'); $size = filesize($file); $length = $size; $start = 0; $end = $size - 1; header('Content-type: video/mp4'); header("Accept-Ranges: bytes"); if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $start; $c_end = $end; list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); if (strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); exit; } if ($range[0] == '-'){ $c_start = $size - substr($range, 1); } else { $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size; } $c_end = ($c_end > $end) ? $end : $c_end; if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); exit; } $start = $c_start; $end = $c_end; $length = $end - $start + 1; fseek($fp, $start); header('HTTP/1.1 206 Partial Content'); } header("Content-Range: bytes $start-$end/$size"); header("Content-Length: ".$length); $buffer = 1024 * 8; while(!feof($fp) && ($p = ftell($fp)) <= $end) { if ($p + $buffer > $end) { $buffer = $end - $p + 1; } set_time_limit(0); ob_clean(); echo fread($fp, $buffer); flush(); } fclose($fp); exit();
Advertisement
Answer
So here’s a basic solution to cache a remote file locally so you can re-use your code:
if (substr($path, 0, 6) === 'http://' || substr($path, 0, 7) === 'https://') { $file = md5($path); if (!file_exists($file)) { $urlStream = fopen($path, 'r'); $dest = fopen($file, 'w'); stream_copy_to_stream($urlStream, $dest); fclose($urlStream); fclose($dest); } } else { $file = $path; } $fp = @fopen($file, 'rb'); $size = filesize($file); $length = $size; $start = 0; $end = $size - 1; header('Content-type: video/mp4'); header("Accept-Ranges: bytes"); if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $start; $c_end = $end; list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); if (strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); exit; } if ($range[0] == '-'){ $c_start = $size - substr($range, 1); } else { $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size; } $c_end = ($c_end > $end) ? $end : $c_end; if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); exit; } $start = $c_start; $end = $c_end; $length = $end - $start + 1; fseek($fp, $start); header('HTTP/1.1 206 Partial Content'); } header("Content-Range: bytes $start-$end/$size"); header("Content-Length: ".$length); $buffer = 1024 * 8; while(!feof($fp) && ($p = ftell($fp)) <= $end) { if ($p + $buffer > $end) { $buffer = $end - $p + 1; } set_time_limit(0); ob_clean(); echo fread($fp, $buffer); flush(); } fclose($fp);
This will create a file based on the accessed URL. You might want to modify the path you store these files in but this is the general idea. The advantage is you will only need to cache the file once, however you may need to use some process to occasionally clean up the cache (like a scheduled task or something like that)