Я пытаюсь прочитать файл mp4 с PHP, и теперь я делаю следующее:
<?php header("Content-Length: filesize"); readfile('file.mp4'); ?>
но таким образом я не могу пропустить или даже вернуться, пока видео не будет загружено на 100%. Конечно, когда я читаю непосредственно из файла (video.mp4), все идет хорошо.
Благодарю.
Вам нужно реализовать функцию пропуска в PHP. Это фрагмент кода, который сделает это.
<?php $path = 'file.mp4'; $size=filesize($path); $fm=@fopen($path,'rb'); if(!$fm) { // You can also redirect here header ("HTTP/1.0 404 Not Found"); die(); } $begin=0; $end=$size; if(isset($_SERVER['HTTP_RANGE'])) { if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) { $begin=intval($matches[0]); if(!empty($matches[1])) { $end=intval($matches[1]); } } } if($begin>0||$end<$size) header('HTTP/1.0 206 Partial Content'); else header('HTTP/1.0 200 OK'); header("Content-Type: video/mp4"); header('Accept-Ranges: bytes'); header('Content-Length:'.($end-$begin)); header("Content-Disposition: inline;"); header("Content-Range: bytes $begin-$end/$size"); header("Content-Transfer-Encoding: binary\n"); header('Connection: close'); $cur=$begin; fseek($fm,$begin,0); while(!feof($fm)&&$cur<$end&&(connection_status()==0)) { print fread($fm,min(1024*16,$end-$cur)); $cur+=1024*16; usleep(1000); } die();
в<?php $path = 'file.mp4'; $size=filesize($path); $fm=@fopen($path,'rb'); if(!$fm) { // You can also redirect here header ("HTTP/1.0 404 Not Found"); die(); } $begin=0; $end=$size; if(isset($_SERVER['HTTP_RANGE'])) { if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) { $begin=intval($matches[0]); if(!empty($matches[1])) { $end=intval($matches[1]); } } } if($begin>0||$end<$size) header('HTTP/1.0 206 Partial Content'); else header('HTTP/1.0 200 OK'); header("Content-Type: video/mp4"); header('Accept-Ranges: bytes'); header('Content-Length:'.($end-$begin)); header("Content-Disposition: inline;"); header("Content-Range: bytes $begin-$end/$size"); header("Content-Transfer-Encoding: binary\n"); header('Connection: close'); $cur=$begin; fseek($fm,$begin,0); while(!feof($fm)&&$cur<$end&&(connection_status()==0)) { print fread($fm,min(1024*16,$end-$cur)); $cur+=1024*16; usleep(1000); } die();
Больше производительности
Обратите внимание, что это не самый эффективный способ сделать это, потому что весь файл должен пройти через PHP, поэтому вам просто нужно попробовать, как это происходит для вас.
Предполагая причину, по которой вы хотите это сделать, это ограничить доступ, и вам потребуется больше эффективности, вы можете использовать флаг для веб-сервера.
Apache с модулем X-Sendfile или lightty ( здесь информация nginx )
$path = 'file.mp4'; header("X-Sendfile: $path"); die();
Это немного более продвинутый, и вы должны использовать его только в том случае, если вам это нужно, но он расслаблен, чтобы узнать, что у вас есть опция обновления, когда вы начинаете с чего-то, что довольно легко, но имеет посредственную производительность.
Я нашел намного более дешевый способ PHP, экспериментируя с принятым решением. Хотя я не тестировал это против X-Sendfile, я подозреваю, что производительность еще лучше для вашего сайта, поскольку это означает более короткий файл Apache.
Вам нужен только следующий код, который можно выпустить для поиска .mp4 видео с PHP (не тестировался с .webm или другими типами):
$file='path/file.mp4'; header('Content-Type: video/mp4'); #Optional if you'll only load it from other pages header('Accept-Ranges: bytes'); header('Content-Length:'.filesize($file)); readfile($file);
Гораздо чище и быстрее; код принятого ответа привел к тому, что видеозахват очень долго загружался по какой-то причине, загрузка видео с помощью этого кода была мгновенной (оба теста были на локальном сервере с видеоматериалом размером 7,25 МБ).
Протестировано с видеоиграми Chrome, Firefox и Edge по умолчанию.
Изменить: проверено без header('Content-Type: video/mp4');
, он по-прежнему работает, если файл загружен с другой страницы! Если вы напрямую обращаетесь к URL-адресу, видеопроигрывателя не будет; код будет просто распечатан.