当通过PHP加载时,在Chrome中无法查找WebM文件(其他浏览器工作)


WebM file not seekable in Chrome when loaded through PHP (other browsers work)

我遇到了一个令人难以置信的问题,我似乎无法解决。

通过PHP提供WebM文件在我的世界里并不是什么新鲜事,我什至知道如何使用HTTP 206部分内容。但出于某种原因,Chrome不喜欢它。

简单的HTML5视频播放

<video width="640" height="360" poster="picture/preview/V00000006.jpg" controls="controls" preload>
    <source type="video/webm" src="/video/V00000006.webm">
</video>

/video/V00000006.webm在 Apache 中重写为 PHP 文件的地方,可以正常播放。但是在Chrome中,搜索栏无效。单击搜索栏时,播放器将冻结并不再播放,直到页面刷新。火狐处理得很好!

如果我/video/V00000006.webm更改为指向同一视频的直接链接,它可以正常工作。我什至比较了两个版本(有和没有 PHP(之间的网络请求,第一个请求几乎没有任何区别,但第二个请求在 PHP 交付的视频中失败。

Apache交付的视频文件的初始请求和搜索请求:

    请求网址:http://mytestserver.net/movie1152x720.webm    请求方式:获取    状态代码:206 部分内容    请求标头    接受:*/*    Accept-Encoding:identity;q=1, *;q=0    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4    缓存控制:无缓存    连接方式:保持活动状态    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0;用户密码=;用户电子邮件=    主机:我的测试服务器网    杂注:无缓存    范围:字节=0-    Referer:http://mytestserver.net/video.html    用户代理:Mozilla/5.0 (X11;Linux x86_64( AppleWebKit/537.36 (KHTML, like Gecko( Chrome/33.0.1750.146 Safari/537.36    响应标头    接受范围:字节    连接方式:关闭    内容长度:4446451    内容范围:字节 0-4446450/4446451    内容类型:视频/网络    日期:2014年4月11日星期五 13:07:30 GMT    ETag:"d2d0027-43d8f3-b91417c0"    最后修订日期:星期五, 11 四月 2014 12:46:31 GMT    服务器:Apache/2.2.3 (CentOS(    --    请求网址:http://mytestserver.net/movie1152x720.webm    请求方式:获取    状态代码:206 部分内容    请求标头    接受:*/*    Accept-Encoding:identity;q=1, *;q=0    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4    缓存控制:无缓存    连接方式:保持活动状态    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0;用户密码=;用户电子邮件=    主机:我的测试服务器网    杂注:无缓存    范围:字节=4445881-    Referer:http://mytestserver.net/video.html    用户代理:Mozilla/5.0 (X11;Linux x86_64( AppleWebKit/537.36 (KHTML, like Gecko( Chrome/33.0.1750.146 Safari/537.36    响应标头    接受范围:字节    连接方式:关闭    内容长度:570    内容范围:字节 4445881-4446450/4446451    内容类型:视频/网络    日期:2014年4月11日星期五 13:09:02 GMT    ETag:"d2d0027-43d8f3-b91417c0"    最后修订日期:星期五, 11 四月 2014 12:46:31 GMT    服务器:Apache/2.2.3 (CentOS(

PHP 流视频的初始请求和查找请求:

    请求网址:http://mytestserver.net/video/V00000006.webm    请求方式:获取    状态代码:206 部分内容    请求标头    接受:*/*    Accept-Encoding:identity;q=1, *;q=0    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4    缓存控制:无缓存    连接方式:保持活动状态    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0;用户密码=;用户电子邮件=    主机:我的测试服务器网    杂注:无缓存    范围:字节=0-    Referer:http://mytestserver.net/video.html    用户代理:Mozilla/5.0 (X11;Linux x86_64( AppleWebKit/537.36 (KHTML, like Gecko( Chrome/33.0.1750.146 Safari/537.36    响应标头    接受范围:字节    缓存控制:无存储、无缓存、必须重新验证、检查后=0、预检查=0    连接方式:关闭    内容长度:8566268    内容范围:字节 0-8566267/8566268    内容类型:视频/网络    日期:2014年4月11日星期五 13:31:27 GMT    到期:星期四, 19 十一月 1981 08:52:00 GMT    杂注:无缓存    服务器:Apache/2.2.3 (CentOS(    X-Powered-by:PHP/5.3.27    --    请求网址:http://mytestserver.net/video/V00000006.webm    请求标头 注意:显示临时标头。    Accept-Encoding:identity;q=1, *;q=0    缓存控制:无缓存    杂注:无缓存    范围:字节=4338314-    Referer:http://mytestserver.net/video.html    用户代理:Mozilla/5.0 (X11;Linux x86_64( AppleWebKit/537.36 (KHTML, like Gecko( Chrome/33.0.1750.146 Safari/537.36

请注意,第二个请求未完成,将显示临时标头

我尝试更改缓存标头,将其设置为将来,将它们设置为空白并使用文件附件标头

我尝试了很多摆

弄服务代码,但最近我最终得到了一个简单的例子。

<?php
$path = 'test.webm';
$size=filesize($path);
$fm=@fopen($path,'rb');
if(!$fm) {
  header ("HTTP/1.0 404 Not Found");
  die();
}
$begin=0;
$end = $size-1;
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/webm");
header('Accept-Ranges: bytes');
header('Content-Length:'.($end-$begin+1));
header("Content-Disposition: inline;");
header("Content-Range: bytes $begin-$end/$size");
header("Content-Transfer-Encoding: binary'n");
header('Connection: close');
ob_get_clean();
flush();
$f = fopen($path, 'r');
fseek($f, $offset);
$pos = 0;
$length = $end-$begin;
while($pos < $length)
{
    $chunk = min($length-$pos, 1024);
    echo fread($f, $chunk);
    flush();
    $pos += $chunk;
}
?>

请注意,直接在浏览器中输入 PHP 提供的视频 URL 与在 HTML 页面中显示它没有区别。

我希望有人能回答为什么寻求可能行不通。如果您有任何建议,请告诉我。

谢谢!

供大家日后参考:

  1. PHP 中HTTP_RANGE的在线示例充满了错误
  2. Chrome在解释网络错误方面非常糟糕
  3. 尺寸很重要!

简而言之,我的问题是由于我的PHP脚本计算并返回了错误的数字。Chrome 会表现得好像它甚至没有尝试完成网络请求,这使得调试变得困难。

现在,我接听了所有网络调用,并通过cURL(在我的Linux控制台中(拉取它们。在这里,我会得到一个更有用的错误,例如 curl:(18( 传输关闭,剩余 1 个字节要读取

内容长度的 1 字节错误会使 Chrome 取消网络请求,并且不会向您显示它收到的响应标头以及取消请求的原因。

这是我的工作代码,包含内容范围和内容长度的工作计算。 $filesize = 文件大小($file(;

$offset = 0;
$length = $filesize;
$partialContent = false;
if(isset($_SERVER['HTTP_RANGE']))
{
    $partialContent = true;
    if(!preg_match('/bytes=('d+)-('d+)?/', $_SERVER['HTTP_RANGE'], $matches))
    {
        header('HTTP/1.1 416 Requested Range Not Satisfiable');
        header('Content-Range: bytes */' . $filesize);
        exit;
    }
    $offset = intval($matches[1]);
    if(isset($matches[2]))
    {
        $end = $intval($matches[2]);
        if($offset > $end)
        {
            header('HTTP/1.1 416 Requested Range Not Satisfiable');
            header('Content-Range: bytes */' . $filesize);
            exit;
        }
        $length = $end - $offset;
    }
    else
        $length = $filesize - $offset;
}
header('Content-Length: ' . $length);
if($partialContent)
{
     header('HTTP/1.1 206 Partial Content');
     header('Content-Range: bytes ' . $offset . '-' . ($offset + $length - 1) . '/' . $filesize);
     // A full-length file will indeed be "bytes 0-x/x+1", think of 0-indexed array counts
}

请注意,上面的代码片段仅包含与部分内容相关的代码,您仍然需要其他标头等才能实际使用它。

如果有人感兴趣,下面是我读出文件的代码。我在网上看到了很多不好和错误的建议,但我认为我的建议很干净。

$f = fopen($file, 'r');
fseek($f, $offset);
$pos = 0;
while($pos < $length)
{
    $chunk = min($length-$pos, 1024*8);
    echo fread($f, $chunk);
    flush();
    ob_flush();
    $pos += $chunk;
}

结案,祝大家好运:-(