videos - Usando php para producir un video mp4
video html5 android (4)
Ok, básicamente, tengo un proyecto que requiere que los videos estén ocultos para los usuarios mientras aún puedan verlos (usando php). esto es lo que obtuve hasta ahora:
El archivo video.php tiene esto:
<?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();
?>
y el archivo html que se supone que muestra esto está usando html5 como sería de esperar. ahora aquí está la cosa ... cuando incruste directamente esto (no), funciona. pero no funciona en mi iPhone y no funciona en la etiqueta ... si utilizo el archivo directo en lugar del envoltorio de php, todo funciona bien, también en mi iPhone ...
así que supongo que mi pregunta para este es esta: ¿cuál es la información correcta del encabezado () para replicar perfectamente un mp4 que se puede transmitir vía iPhone y HMTL5?
Solución derivada de: http://mobiforge.com/developing/story/content-delivery-mobile-devices
archivo 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();
?>
Aquí hay un código recortado que hará lo que quiera ( de esta pregunta ). La solución PHP parece más elegante y agrega una solución más eficiente que podría funcionar que utiliza el servidor web para servir el contenido.
<?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();
Más rendimiento
Tenga en cuenta que esta no es la forma más eficiente de hacerlo, ya que todo el archivo debe pasar por PHP, por lo que solo tendrá que probar cómo funciona.
Suponiendo que la razón por la que desea hacer esto es restringir el acceso, y necesita más eficiencia más adelante, puede usar un indicador para el servidor web.
Apache con módulo X-Sendfile o lightty ( información de nginx aquí )
$path = ''file.mp4'';
header("X-Sendfile: $path");
die();
Esto es un poco más avanzado y solo debe usarlo si lo necesita, pero es relajante saber que tiene una opción de actualización cuando comienza con algo que es bastante fácil pero tiene un rendimiento mediocre.
Este código fue muy útil para mí, pero me encontré con problemas porque estoy usando sesiones vars, y las colas PHP acceden a las sesiones. Si un video se estaba cargando, todas las solicitudes de AJAX eran imposibles, etc. Por lo tanto, asegúrese de llamar a session_write_close()
antes de iniciar la salida.
Los Iphones usan algo llamado byte-ranges para solicitudes de audio y video. Vea este enlace para una solución. Está en el Apéndice A.
http://mobiforge.com/developing/story/content-delivery-mobile-devices
Sí, es fácil de hacer. No es necesario configurar esos encabezados manualmente. Deje que el servidor lo haga automáticamente.
Aquí hay un script de trabajo
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);