3

我正在 LAMP 环境中开发一个 CakePHP 1.3 项目,我们在其中存储许多视频,/app/webroot/并使用CakePHP 的媒体视图提供它们(我们这样做是因为我们不希望直接访问这些文件)。但是,我无法通过媒体视图将这些视频提供给 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 媒体视图在 iOS 设备上提供视频的运气或经验?提前致谢!

4

1 回答 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因为给定的数字范围取决于请求。我们进行了以下更改(并在媒体视图调用中将下载布尔值设置为 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 设备上到达文件末尾,它似乎有点不稳定。)

于 2012-11-20T01:36:35.443 回答