PHP:iPad不播放由PHP提供的MP4视频,但如果直接访问则可以

Kai*_*ack 11 php video html5 ipad

我已经试图找到这个问题的解决方案已经有好几天了,我尝试了所有可以在stackoverflow和其他平台上找到的建议.而且,仍然没有解决方案.

我正在通过HTML5视频标记嵌入视频:

 <video poster="thumb.png" controls="controls" preload="none" width="640" height="480">
    <source src="provider.php?secure=12345" type="video/mp4">
 </video>
Run Code Online (Sandbox Code Playgroud)

我尝试通过PHP传送MP4视频文件,而不是直接链接它.直接链接mp4文件工作并播放文件!

测试:

  1. 视频文件:https://github.com/q2apro/videotest-ipad/raw/master/video.mp4(在iPad上播放)
  2. PHP加载的视频文件具有相同的标题:https://github.com/q2apro/videotest-ipad/blob/master/test-headers.php(不在iPad上播放) - 源码
  3. PHP用Byte Ranges加载的视频文件:https://github.com/q2apro/videotest-ipad/blob/master/test-byterange.php(不在iPad上播放) - 源码
  4. PHP用Byte Ranges加载的视频文件(另一个脚本):https://github.com/q2apro/videotest-ipad/blob/master/test-byterange-2.php(不在iPad上播放,警告"操作可能没有完成") - 源代码

笔记:

  • 上面的所有链接都是直接访问/播放视频文件而没有嵌入标记
  • 视频适用于Windows中的所有浏览器(但不适用于iPad上的Safari/Chrome,也可能不适用于iPhone)

我的设置:

  • 测试设备:iPad iOS 6(我没有mac,无法调试)
  • 带Safari和Chrome的iPad(试过两种浏览器)
  • 我的服务器是来自domainfactory的共享托管
  • 调试工具:Firefox 29 Web Developer Console/WIN7

在.htaccess测试文件夹设置MIME类型,并接受-范围:

AddType video/mp4 .mp4 

<IfModule mod_headers.c>
   Header set Accept-Ranges "bytes"
</IfModule>
Run Code Online (Sandbox Code Playgroud)


即使我创建了相同的标题(比较测试URL 1.和2.),iPad也没有通过PHP请求播放文件.

相反,我总是得到这个严格的播放按钮:

ipad strikedthrough播放按钮

标题为1.(直接mp4调用):

mp4直拨电话

标题2.与上面相同的标题,但由PHP设置(由PHP提供的mp4):

在此输入图像描述

-

我也尝试使用PHP的fread(),fpassthru()和file_get_contents()读取整个视频文件并将其发送到浏览器,但iPad始终显示无法播放图标.

-

我的托管服务器不提供Connection keep-alive,这可能是个问题吗?iPad解释.php与.mp4不同吗?

有人可以帮助我摆脱痛苦吗?我完全陷入困境.



PS:我试过考虑的事情:

  • 字节范围请求(206部分内容)01 02 03
  • 正确的视频编码04
  • 测试时使用其他编码视频
  • 在php脚本中禁用了zlib.output_compression



更新:调试控制台

我终于得到了朋友的MAC,连接了iPad,在Mac上的Safari中打开了调试控制台,在iPad上加载了页面并检查了Mac上出现的错误消息(顺便说一句,苹果强迫我们开发的更复杂...).对于所有测试脚本,将出现此错误:

Failed to load resource: Plug-in handled load
Run Code Online (Sandbox Code Playgroud)

Kai*_*ack 15

哇,这太难了!


1.第一个主要问题

事实证明,没有编码问题,但在视频转换过程中设置的mp4容器标题存在问题 - iPad显然存在为渐进式流式传输准备的MP4视频的问题.

首先,我发现,在交谈这里.转换视频后,我总是使用工具MP4 Fast Start为渐进流准备视频文件.这对于将视频文件分段(逐步)流式传输到Flash Player是必要的,因此它不会加载整个文件(并且用户必须等待).

使用Handbrake有一个类似的设置,称为Web Optimized.它也是这样的:

Web Optimized
Also known as "Fast Start"
This places the container header at the start of the file, optimizing it for streaming across the web.
Run Code Online (Sandbox Code Playgroud)

如果您启用此功能并转换视频,iPad将无法播放视频文件!相反,您会收到错误"操作无法完成".

ipad strikedthrough播放按钮

检查并自己测试:视频测试资源.


2.第二个问题

在生产环境中,我总是使用PHP来检查引用者.我发现,iPad不会发送引用信息.这也会阻止流式传输,您还会看到无法播放的符号(通过播放图标).


3.第三个问题

我找不到原因,但iPad只接受来自此脚本的视频流http://ideone.com/NPSlw5

<?php
// disable zlib so that progress bar of player shows up correctly
if(ini_get('zlib.output_compression')) {
    ini_set('zlib.output_compression', 'Off'); 
}

$folder = '.'; 
$filename = 'video.mp4';
$path = $folder.'/'.$filename;

// from: http://licson.net/post/stream-videos-php/
if (file_exists($path)) {
    // Clears the cache and prevent unwanted output
    ob_clean();

    $mime = "video/mp4"; // The MIME type of the file, this should be replaced with your own.
    $size = filesize($path); // The size of the file

    // Send the content type header
    header('Content-type: ' . $mime);

    // Check if it's a HTTP range request
    if(isset($_SERVER['HTTP_RANGE'])){
        // Parse the range header to get the byte offset
        $ranges = array_map(
            'intval', // Parse the parts into integer
            explode(
                '-', // The range separator
                substr($_SERVER['HTTP_RANGE'], 6) // Skip the `bytes=` part of the header
            )
        );

        // If the last range param is empty, it means the EOF (End of File)
        if(!$ranges[1]){
            $ranges[1] = $size - 1;
        }

        // Send the appropriate headers
        header('HTTP/1.1 206 Partial Content');
        header('Accept-Ranges: bytes');
        header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range

        // Send the ranges we offered
        header(
            sprintf(
                'Content-Range: bytes %d-%d/%d', // The header format
                $ranges[0], // The start range
                $ranges[1], // The end range
                $size // Total size of the file
            )
        );

        // It's time to output the file
        $f = fopen($path, 'rb'); // Open the file in binary mode
        $chunkSize = 8192; // The size of each chunk to output

        // Seek to the requested start range
        fseek($f, $ranges[0]);

        // Start outputting the data
        while(true){
            // Check if we have outputted all the data requested
            if(ftell($f) >= $ranges[1]){
                break;
            }

            // Output the data
            echo fread($f, $chunkSize);

            // Flush the buffer immediately
            @ob_flush();
            flush();
        }
    }
    else {
        // It's not a range request, output the file anyway
        header('Content-Length: ' . $size);

        // Read the file
        @readfile($path);

        // and flush the buffer
        @ob_flush();
        flush();
    }

}
die();

?>
Run Code Online (Sandbox Code Playgroud)


我希望这些信息能够帮助其他人解决问题.


更新:三个月后,在生产环境中,我的一些用户仍然报告了播放问题.Safari似乎还有另一个问题.我建议他们使用Chrome for iPad,修复它.



PS:几天的研究和麻烦只是播放一个视频文件,顺便说一句,它运行在所有其他设备上.这再一次向我证明,苹果公司因为良好的营销而获得成功,而不是因为出色的软件.


归档时间:

查看次数:

14811 次

最近记录:

6 年,11 月 前