Utiliser php pour produire une vidéo mp4

Ok fondamentalement j'ai un projet qui exige que les vidéos soient cachées aux utilisateurs tout en étant capable de les voir (en utilisant php). voici ce que j'ai obtenu jusqu'à présent:

La vidéo.fichier php a ceci:

<?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();
?>

et le fichier html qui est supposé afficher ceci utilise html5 comme prévu. maintenant, voici la chose.. quand je l'intègre directement (pas) cela fonctionne. mais il ne fonctionne pas sur mon iPhone et ne fonctionne pas dans la balise... si j'utilise le fichier direct au lieu du php wrapper, tout fonctionne bien, sur mon iPhone...

alors je suppose que ma question pour celle-ci est la suivante: Quelles sont les informations d'en-tête() appropriées pour répliquer parfaitement un mp4 qui peut être diffusé via iPhone et HMTL5?

Solution dérivée de:http://mobiforge.com/developing/story/content-delivery-mobile-devices

vidéo.fichier 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();
?>
26
demandé sur tereško 2011-05-08 01:18:49

4 réponses

les Iphones utilisent quelque chose appelé byte-ranges pour les requêtes audio et vidéo. Voir ce lien pour une solution. C'est à L'Annexe A.

http://mobiforge.com/developing/story/content-delivery-mobile-devices

14
répondu sreimer 2011-05-07 21:31:05

voici un code snippé qui fera ce que vous voulez (à partir de cette question). La solution PHP semble plus élégante, et elle ajoute une solution plus efficace qui pourrait fonctionner qui utilise le serveur web pour servir le contenu.

<?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();

Plus De Performance

notez que ce n'est pas la façon la plus efficace de le faire, parce que l'ensemble du fichier doit passer par PHP, donc vous aurez juste besoin d'essayer comment ça se passe pour vous.

en supposant que raison pour laquelle vous voulez faire est de restreindre l'accès, et vous avez besoin de plus d'efficacité, plus tard, vous pouvez utiliser un drapeau pour le serveur web.

Apache avec module X-Sendfile ou lightty (nginx info ici)

$path = 'file.mp4';
header("X-Sendfile: $path");
die();

C'est un peu plus avancé et vous ne devriez l'utiliser que si vous en avez besoin, mais c'est relaxant de savoir que vous avez une option de mise à niveau lorsque vous commencez avec quelque chose qui est plutôt facile mais qui a des performances médiocres.

6
répondu cmc 2017-05-23 12:09:12

ce code était très pratique pour moi, mais j'ai eu des problèmes parce que j'utilise les vars de session, et les accès PHP aux sessions. Si une vidéo était chargée, toutes les requêtes AJAX étaient impossibles,etc. Assurez-vous donc d'appeler session_write_close() avant de lancer la sortie.

1
répondu jefftimesten 2012-02-16 08:41:37

Oui, c'est facile à faire. Pas besoin de régler ces en-têtes manuellement. Laisser le serveur le faire automatiquement.

Heres un travail 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);
1
répondu WebAdmin at dekho-ji.com 2014-01-17 10:47:55