playsinline attribute php html5-video ios

php - attribute - playsinline video html5



MP4 se reproduce cuando se accede directamente, pero no cuando se lee a través de PHP, en iOS (6)

Utilizo un script PHP para validar las solicitudes de video antes de servirlas. Este script funciona como se espera en el escritorio, con Safari y Chrome. Pero en iOS, me sale un botón de reproducción roto.

Estoy seguro de que el video está codificado correctamente para iPhone / iPad, porque cuando lo accedo directamente, funciona como se esperaba.

El código PHP relevante:

$file_name = ''test-video.mp4''; $file_size = (string)(filesize($file_name)); header(''Content-Type: video/mp4''); header(''Content-Length: ''.$file_size); readfile_chunked($file_name); exit;

( readfile_chunked() es similar a readfile() pero para archivos muy grandes, que se encuentran en los comentarios en la página del manual de PHP: http://php.net/manual/en/function.readfile.php . En cualquier caso, test-video.mp4 es solo de ~ 5 MB, que es menor que el límite de memoria, y en este caso realmente puedo sustituirlo en el readfile() normal readfile() y producir el mismo comportamiento.

Los encabezados que obtengo cuando test-video.mp4 directamente son:

Accept-Ranges:bytes Connection:Keep-Alive Content-Length:5558749 Content-Type:video/mp4 Date:Sun, 27 Jun 2010 21:02:09 GMT Etag:"1c04757-54d1dd-489944c5a6400" Keep-Alive:timeout=10, max=30 Last-Modified:Tue, 22 Jun 2010 01:25:36 GMT Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635

Los encabezados del script PHP son:

Connection:Keep-Alive Content-Disposition:inline; filename="test-video.mp4" Content-Length:5558749 Content-Type:video/mp4 Date:Sun, 27 Jun 2010 21:03:32 GMT Keep-Alive:timeout=10, max=15 Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635 X-Powered-By:PHP/5.2.13

He intentado muchas permutaciones diferentes de encabezados, incluso comparándolos exactamente con los de una solicitud directa, sin éxito.

¿Alguien ha tenido éxito sirviendo video HTML5 a través de PHP, en iOS?

[Nota: probaría usar X-Sendfile, pero el sitio está en un host compartido con acceso muy limitado.]

EDITAR: estaba leyendo que iOS puede ser sensible acerca de las extensiones de archivo, así que intenté configurar una RewriteRule que vuelve a escribir las solicitudes de MP4 en mi script PHP original, pero eso tampoco ayudó.


Como se indicó anteriormente para transmitir o reproducir videos MP4 usando PHP, deberá manejar los rangos de bytes si desea una reproducción adecuada en Safari y iOS.

rangeDownload() función rangeDownload() mencionada en las respuestas anteriores hace el trabajo bastante bien.

Quiero mencionar otra pieza de este rompecabezas: asegúrese de que la fuente en el video termine con .mp4 como en <video source="url/yourfile.php/referenceForFile.mp4"> . Esto hace que el navegador sea un archivo de video, y comienza a tratarlo como uno solo.

Dentro de yourfile.php , puede tomar la referencia entrante para su archivo usando $_SERVER[''PATH_INFO''] o dentro de REQUEST_URI . No es necesario pasarlo como un ?id=someId.mp4 , el enfoque de barra directa se parece más a un archivo real.

En resumen, desde mi experiencia para servir un archivo de video desde PHP correctamente, necesitará:

  • Soporte de rango de bytes. El navegador le dice al servidor qué parte del archivo necesita, y el servidor necesita responder con ese contenido de rango de bytes.
  • Tenga su moov atom al principio del archivo (puede usar ffmpeg''s -movflags +faststart o MP4Box )
  • <video source="...file.mp4"> El atributo de origen de la etiqueta de video debe verse como un archivo .mp4 . Sin esto, mis videos solo se reproducían en Chrome y no en Safari / iOS.
  • Reproductor HTML5 directo, o puedes usar una biblioteca como videojs

Escribí esto en base a mi experiencia con la publicación de miles de videos en mi sitio web de videos musicales. Si bien este podría no ser el caso para todos, pero encontré que esta configuración de navegador cruzado y dispositivo funcionó como se esperaba.


Si lees el archivo de la URL de http, en lugar de filsize (), la función de tu usuario debajo del código para obtener el tamaño del archivo

function getFileSize($file) { $ch = curl_init($file); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $data = curl_exec($ch); curl_close($ch); $contentLength=0; if (preg_match(''/Content-Length: (/d+)/'', $data, $matches)) { // Contains file size in bytes $contentLength = (int)$matches[1]; } return $contentLength; }


Si lo maneja usted mismo, entonces también deberá manejar las solicitudes de rango de bytes.


Tenga en cuenta que este es el código ( https://mobiforge.com/design-development/content-delivery-mobile-devices ) es un salvavidas. Sin embargo estar en la búsqueda de la línea

"if ($ range {0} == ''-'') {" o "if ($ range0 == ''-'') {"

debería ser

if ($ range [0] == ''-'') {

Este error tipográfico resultó en un tiempo muy largo para descubrir por qué no funcionó.


Tratar:

$arquivo_caminho = ''path/file'' if (is_file($arquivo_caminho)){ header("Content-type: video/mp4"); // change mimetype if (isset($_SERVER[''HTTP_RANGE''])){ // do it for any device that supports byte-ranges not only iPhone rangeDownload($arquivo_caminho); } else { header("Content-length: " . filesize($arquivo_caminho)); readfile($arquivo_caminho); } // fim do if } // fim do if function rangeDownload($file){ $fp = @fopen($file, ''rb''); $size = filesize($file); // File size $length = $size; // Content length $start = 0; // Start byte $end = $size - 1; // End byte // Now that we''ve gotten so far without errors we send the accept range header /* At the moment we only support single ranges. * Multiple ranges requires some more work to ensure it works correctly * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 * * Multirange support annouces itself with: * header(''Accept-Ranges: bytes''); * * Multirange content must be sent with multipart/byteranges mediatype, * (mediatype = mimetype) * as well as a boundry header to indicate the various chunks of data. */ header("Accept-Ranges: 0-$length"); // header(''Accept-Ranges: bytes''); // multipart/byteranges // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 if (isset($_SERVER[''HTTP_RANGE''])){ $c_start = $start; $c_end = $end; // Extract the range string list(, $range) = explode(''='', $_SERVER[''HTTP_RANGE''], 2); // Make sure the client hasn''t sent us a multibyte range if (strpos($range, '','') !== false){ // (?) Shoud this be issued here, or should the first // range be used? Or should the header be ignored and // we output the whole content? header(''HTTP/1.1 416 Requested Range Not Satisfiable''); header("Content-Range: bytes $start-$end/$size"); // (?) Echo some info to the client? exit; } // fim do if // If the range starts with an ''-'' we start from the beginning // If not, we forward the file pointer // And make sure to get the end byte if spesified if ($range{0} == ''-''){ // The n-number of the last bytes is requested $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; } // fim do if /* Check the range and make sure it''s treated according to the specs. * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */ // End bytes can not be larger than $end. $c_end = ($c_end > $end) ? $end : $c_end; // Validate the requested range and return an error if it''s not correct. 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"); // (?) Echo some info to the client? exit; } // fim do if $start = $c_start; $end = $c_end; $length = $end - $start + 1; // Calculate new content length fseek($fp, $start); header(''HTTP/1.1 206 Partial Content''); } // fim do if // Notify the client the byte range we''ll be outputting header("Content-Range: bytes $start-$end/$size"); header("Content-Length: $length"); // Start buffered download $buffer = 1024 * 8; while(!feof($fp) && ($p = ftell($fp)) <= $end){ if ($p + $buffer > $end){ // In case we''re only outputtin a chunk, make sure we don''t // read past the length $buffer = $end - $p + 1; } // fim do if set_time_limit(0); // Reset time limit for big files echo fread($fp, $buffer); flush(); // Free up memory. Otherwise large files will trigger PHP''s memory limit. } // fim do while fclose($fp); } // fim do function


Tuve un problema con ese código.

Fijar:

set_time_limit(0); // Reset time limit for big files ob_clean(); //added echo fread($fp, $buffer); flush(); // Free up memory. Otherwise large files will trigger PHP''s memory limit.