By making a brief note in the script link there were some "problems", this script was probably set to .htaccess
specific , ie it would have to be adjusted both need, same goes for Ngnix.
I assume this is due to the $_SERVER['PATH_INFO']
that is only generated by rewriting, except that with the experience that has line 4 it will not work ( SCRIPT_FILENAME
). Other than that the author put a set_time_limit(0);
in the middle of the whille, which I think is redundancy. I can not say that this compromises the operation and I do not want to criticize anyone, I'm just stating that the script is made to work in a specific situation, I've re-scripted it to work with a simple GET (querystring):
<?php
set_time_limit(0); //Remove o limite
//Pega o mimetype
function mimeType($file)
{
$mimetype = false;
if (class_exists('finfo')) {//PHP5.4+
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $file);
finfo_close($finfo);
} else if (function_exists('mime_content_type')) {//php5.3 ou inferiror
$mimetype = mime_content_type($file);
}
return $mimetype;
}
if (empty($_GET['video'])) {
die('Video não definido');
}
//Pega a URL do video
$file = 'videos/' . str_replace('../', '', $_GET['video']);
$mime = mimeType($file);
if (!$mime || strpos($mime, 'video/') !== 0) {
die('Erro ao ler o video ou mime-type inválido');
}
$fp = fopen($file, 'rb');
$size = filesize($file); // File size
$length = $size; // Content length
$start = 0; // Start byte
$end = $size - 1; // End byte
header('Content-type: ' . $mime);
header('Accept-Ranges: 0-' . $length);
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 == '-') {
$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;
}
echo fread($fp, $buffer);
flush();
}
fclose($fp);
If the video address is based on a bank ID, you would need to adjust:
//Exemplo teórico, pode adaptar pro seu ORM ou mysqli, é apenas para esclarecer a lógica
$consulta = $pdo->prepare('SELECT filename FROM videos WHERE id = :id');
//Pega o ID pela QUERYSTRING
$consulta->bindValue(':id', $_GET['videoid'], PDO::PARAM_INT);
$consulta->execute();
$linha = $consulta->fetch(PDO::FETCH_ASSOC);
//Pega a URL do video
$file = 'videos/' . $linha['filename'];
Warning: I'm looking at the docs and a few things about HTTP to better understand the range, I'll fix any shortcomings in the script soon
Tests
In the chrome (opera) I bounded to 3G Fast (simulation), the HTML looked like this:
<video src="range.php?video=1.mp4" controls preload="none"></video><hr>
<video src="range.php?video=2.mp4" controls preload="none"></video><hr>
<video src="range.php?video=3.mp4" controls preload="none"></video><hr>
And in the console:
Igaveplayinthefirstvideoandthendraggedthecontrolforwardandresultedin:
I'mjustnotsurewhyIgeneratedmultiplerequests,butIthinkitmightbethatthescriptisstillnotperfectordownloadingthevideoafter"seek" depends on the machine and / or browser's CODECs of the internet).
Image of "seekbar":