php - 通过 PHP 加载时无法在 Chrome 中查找 WebM 文件(其他浏览器也可以)

标签 php google-chrome ffmpeg html5-video webm

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

通过 PHP 提供 WebM 文件在我的世界中并不是什么新鲜事,我什至知道如何使用 HTTP 206 Partial Content。但是由于某种原因 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 中,搜索栏无效。单击搜索栏时,播放器将卡住并且在页面刷新之前不再播放。 Firefox 处理得很好!

如果我改变 /video/V00000006.webm成为同一个视频的直接链接,它工作得很好。我什至比较了两个版本(使用和不使用 PHP)之间的网络请求,第一个请求几乎没有任何区别,但第二个请求在 PHP 交付的视频中失败。

Apache 提供的视频文件的初始请求和搜索请求:
    Request URL:http://mytestserver.net/movie1152x720.webm
    Request Method:GET
    Status Code:206 Partial Content
    Request Headers
    Accept:*/*
    Accept-Encoding:identity;q=1, *;q=0
    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4
    Cache-Control:no-cache
    Connection:keep-alive
    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0; userPassword=; userEmail=
    Host:mytestserver.net
    Pragma:no-cache
    Range:bytes=0-
    Referer:http://mytestserver.net/video.html
    User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
    Response Headers
    Accept-Ranges:bytes
    Connection:close
    Content-Length:4446451
    Content-Range:bytes 0-4446450/4446451
    Content-Type:video/webm
    Date:Fri, 11 Apr 2014 13:07:30 GMT
    ETag:"d2d0027-43d8f3-b91417c0"
    Last-Modified:Fri, 11 Apr 2014 12:46:31 GMT
    Server:Apache/2.2.3 (CentOS)

    --

    Request URL:http://mytestserver.net/movie1152x720.webm
    Request Method:GET
    Status Code:206 Partial Content
    Request Headers
    Accept:*/*
    Accept-Encoding:identity;q=1, *;q=0
    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4
    Cache-Control:no-cache
    Connection:keep-alive
    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0; userPassword=; userEmail=
    Host:mytestserver.net
    Pragma:no-cache
    Range:bytes=4445881-
    Referer:http://mytestserver.net/video.html
    User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
    Response Headers
    Accept-Ranges:bytes
    Connection:close
    Content-Length:570
    Content-Range:bytes 4445881-4446450/4446451
    Content-Type:video/webm
    Date:Fri, 11 Apr 2014 13:09:02 GMT
    ETag:"d2d0027-43d8f3-b91417c0"
    Last-Modified:Fri, 11 Apr 2014 12:46:31 GMT
    Server:Apache/2.2.3 (CentOS)

Initial request and seek request for PHP-streamed video:

    Request URL:http://mytestserver.net/video/V00000006.webm
    Request Method:GET
    Status Code:206 Partial Content
    Request Headers
    Accept:*/*
    Accept-Encoding:identity;q=1, *;q=0
    Accept-Language:da-DK,da;q=0.8,en-US;q=0.6,en;q=0.4
    Cache-Control:no-cache
    Connection:keep-alive
    Cookie:PHPSESSID=i562540rek172mnv3nk528acj0; userPassword=; userEmail=
    Host:mytestserver.net
    Pragma:no-cache
    Range:bytes=0-
    Referer:http://mytestserver.net/video.html
    User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
    Response Headers
    Accept-Ranges:bytes
    Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Connection:close
    Content-Length:8566268
    Content-Range:bytes 0-8566267/8566268
    Content-Type:video/webm
    Date:Fri, 11 Apr 2014 13:31:27 GMT
    Expires:Thu, 19 Nov 1981 08:52:00 GMT
    Pragma:no-cache
    Server:Apache/2.2.3 (CentOS)
    X-Powered-By:PHP/5.3.27

    --

    Request URL:http://mytestserver.net/video/V00000006.webm
    Request Headers CAUTION: Provisional headers are shown.
    Accept-Encoding:identity;q=1, *;q=0
    Cache-Control:no-cache
    Pragma:no-cache
    Range:bytes=4338314-
    Referer:http://mytestserver.net/video.html
    User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36

Notice how the second request does not complete, Provisional headers are shown.

I have tried altering the cache headers, setting it to the future, setting them blank and using file attachment headers.

I tried fiddling around a lot with the serving code, but lately I have ended up with a simple example.

<?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 页面中显示它没有区别。

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

谢谢!

最佳答案

供大家日后引用:

  • PHP中HTTP_RANGE的在线例子充满了错误
  • Chrome 在解释网络错误方面非常糟糕
  • 大小事项!

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

    现在我接受了所有的网络调用,并通过 cURL(在我的 Linux 控制台中)提取它们。
    在这里,我会得到一个更有用的错误,例如 curl: (18) transfer closed with 1 bytes remaining to read

    这个 1 字节的内容长度错误使 Chrome 取消了网络请求,并且不向您显示它获得的响应 header 以及取消请求的原因。

    这是我的工作代码,内容范围和内容长度的工作计算。
    $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;
    }
    

    结案,
    祝你们好运 :-)

    关于php - 通过 PHP 加载时无法在 Chrome 中查找 WebM 文件(其他浏览器也可以),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23014913/

    相关文章:

    api - 我如何学习 chrome.extension.sendRequest 方法?

    linux - 使用 ffmpeg 从运行 linux 的 Pocketbeagle 通过 UDP 直播网络摄像头视频,缺少什么?

    php - "simple"CollectionType 包含错误

    javascript - 在 ipad chrome 上触发的鼠标滚轮事件

    google-chrome - 在新的 Chrome 选项卡中打开 PDF Blob (Angular 2)

    node.js - 缓冲区类型视频宽高nodejs

    nginx - ffmpeg 转发流有 3 秒延迟

    php - 使用 NGINX 对 PHP 脚本的多个同时请求

    php - MySql - 从中​​选择 - 不要显示重复的单词 - 也许是 "on duplicate key"?

    php - ZF2 : How to make Zend\Validator\Hostname accept url strings with and without http://or https://