使用CakePHP的媒体视图向iPad/iPhone提供视频服务

3
我正在一个LAMP环境下开发一个CakePHP 1.3项目,其中我们将许多视频存储在/app/webroot/之外,并使用CakePHP的Media Views提供服务(因为我们不希望文件直接可访问)。然而,我在通过Media Views向iOS设备(如iPhone、iPad)提供这些视频时遇到了问题。
我可以将测试视频放置在/app/webroot/中的某个位置,并直接在iOS设备上访问它,播放正常,因此我相当确定这不是MOOV问题或其他与视频本身编码有关的问题。据我所知,这与CakePHP处理(或缺乏处理)iOS设备在加载视频时使用的字节范围请求有关。
我发现一篇另一个未被回答的Stack Overflow问题,但它详细描述了一个类似的问题。查看/cake/libs/view/media.php类文件,render()方法内部有一个if语句,它会检查$_SERVER['HTTP_RANGE']值;但据我测试,在CakePHP查找时,这个值似乎没有被设置过。前面提到的离线解决方案也不能解决我的问题,因为它也依赖于对这个值的检查,而我已经验证了在Media View类本身或设置该视图的控制器中都没有找到这个值。
那么,有没有人使用CakePHP Media Views成功地向iOS设备提供视频呢?提前感谢您的帮助!
1个回答

2

在我在网上发布了各种问题后没有得到任何答案,我们又试了一次,最终解决了这个问题。

事实证明,这是Media.php类文件(/cake/libs/view/media.php)中的问题,与它对HTTP_RANGE标头值的期望以及如何格式化随后的标头有关。首先,这里是原始相关代码片段:

$httpRange = env('HTTP_RANGE');
if (isset($httpRange)) {
    list($toss, $range) = explode('=', $httpRange);

    $size = $fileSize - 1;
    $length = $fileSize - $range;

    $this->_header(array(
        'HTTP/1.1 206 Partial Content',
        'Content-Length: ' . $length,
        'Content-Range: bytes ' . $range . $size . '/' . $fileSize));

    fseek($handle, $range);
}

请注意list()调用,它会填充一个$range值,然后被用作数值。然而,在进一步调试头部调用后,我们注意到HTTP_RANGE的值实际上是Range: bytes=0-1000,其中给定的数字范围取决于请求。我们进行了以下更改(并在Media View调用中将下载布尔值设置为true),然后就可以在iOS设备上播放视频了。
$httpRange = env('HTTP_RANGE');
if (isset($httpRange)) {
    $start = 0; //start byte
    $end = $fileSize - 1; //end byte
    $length = $fileSize; //content length

    $c_start = $start; //default value
    $c_end = $end; //default value
    list($toss, $range) = explode('=', $httpRange); //extract range

    //grab range value(s)
    if ($range[0] == '-') {
        $c_start = $fileSize - substr($range, 1);
    } else {
        $range = explode('-', $range);
        $c_start = $range[0];
        $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $fileSize;
    }

    //validate end byte
    $c_end = ($c_end > $end) ? $end : $c_end;

    //set new values
    $start = $c_start;
    $end = $c_end;
    $length = $end - $start + 1;

    $this->_header(array(
        'HTTP/1.1 206 Partial Content',
        'Content-Length: ' . $length,
        'Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize));
    fseek($handle, $start);
}

请注意,这个内容包含了这篇文章的附录A中的大部分逻辑,该逻辑处理了多种情况。(最初我们放弃了很多这样的逻辑,虽然在播放时一切正常,但是当在iOS设备上到达文件结尾时,它似乎有点不稳定。)

我也遇到了同样的问题,但这对我没有用。在我的情况下,$httpRange是空的。你知道可能发生了什么吗?我正在iPad上进行测试。 - Garry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接