Подтвердить что ты не робот

Использование php для вывода видео mp4

Хорошо, в основном у меня есть проект, который требует, чтобы видео были скрыты от пользователей, хотя они все еще могли их видеть (используя php). вот что я получил до сих пор:

В файле video.php есть следующее:

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'path/to/movie.mp4');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_HEADER, 0);
$out = curl_exec($ch);
curl_close($ch);


header('Content-type: video/mp4');
header('Content-type: video/mpeg');
header('Content-disposition: inline');
header("Content-Transfer-Encoding:­ binary");
header("Content-Length: ".filesize($out));
echo $out;
exit();
?>

и html файл, который должен отображать это, использует html5, как и ожидалось. теперь вот вещь.. когда я прямо вставляю это (нет), это работает. но он не работает на моем iPhone и не работает в теге... если я использую прямой файл вместо php-обертки, все работает отлично, на моем iPhone тоже...

поэтому я думаю, что мой вопрос для этого заключается в следующем: какова правильная информация header() для полной репликации mp4, которая может транслироваться через iPhone и HMTL5?

Решение, полученное из: http://mobiforge.com/developing/story/content-delivery-mobile-devices

video.php файл:

<?php
$file = 'path/to/videofile.mp4';
$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: video/mp4');
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;
    }
    set_time_limit(0);
    echo fread($fp, $buffer);
    flush();
}

fclose($fp);
exit();
?>
4b9b3361

Ответ 2

Вот фрагмент кода, который сделает то, что вы хотите (из этого вопроса). Решение PHP кажется более элегантным, и оно добавляет более эффективное решение, которое может работать, которое использует веб-сервер для обслуживания содержимого.

<?php

$path = 'file.mp4';

$size=filesize($path);

[email protected]($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();

Это немного более продвинутый, и вы должны использовать его только в том случае, если он вам нужен, но он расслаблен, чтобы знать, что у вас есть опция обновления, когда вы начинаете с чего-то, что довольно легко, но имеет посредственную производительность.

Ответ 3

Этот код был очень удобен для меня, но я столкнулся с проблемами, потому что я использую сеансовые вары, а PHP - доступ к сеансам. Если видео загружалось, все запросы AJAX были невозможны и т.д. Поэтому перед тем, как начать вывод, обязательно вызовите session_write_close().

Ответ 4

Да, это легко сделать. Не нужно устанавливать эти заголовки вручную. Пусть сервер сделает это автоматически.

Здесь работает script -

ob_start();

if( isset($_SERVER['HTTP_RANGE']) )

$opts['http']['header']="Range: ".$_SERVER['HTTP_RANGE'];

$opts['http']['method']= "HEAD";

$conh=stream_context_create($opts);

$opts['http']['method']= "GET";

$cong= stream_context_create($opts);

$out[]= file_get_contents($real_file_location_path_or_url,false,$conh);

$out[]= $http_response_header;

ob_end_clean();

array_map("header",$http_response_header);

readfile($real_file_location_path_or_url,false,$cong);