3

我有一个<video>and<audio>元素,它通过 Range 请求从我的服务器加载文件(mp4、mp3,没关系)。

然而,该元素似乎只从我的服务器请求结束范围,并且从那里开始尝试直接从字节 0 流式传输到末尾,导致播放器陷入“下载循环”,这使得浏览器暂停所有其他操作,直到下载完成。

范围请求 1

范围请求 2

有谁知道这个问题的解决方案?例如,我是否必须让我的流请求真正结束它的content lengthor accept-ranges

这是来自 Chrome 的完整请求列表,在底部您可以看到对 url 的请求view?watch=v__AAAAAA673pxX只是保持挂起状态,基本上直到element.

全方位的请求历史

简而言之:html5 元素在使用请求时会陷入下载循环,http-range并导致所有其他请求保持“待处理”状态。

更新

该问题已在服务器端解决。

虽然原始流函数实际上会输出每个字节,但我修改了代码以仅输出实际缓冲区的大小。这会强制对elements剩余数据提出新的请求。

此处的一个重要注意事项是返回content-length,accept-ranges并且content-ranges与每个HTTP RANGE请求中的文件大小、开始和结束位置相匹配。

供将来参考:

function stream(){
    $i = $this->start;
    set_time_limit(0);
    while(!feof($this->stream) && $i <= $this->end) {
        $bytesToRead = $this->buffer;
        if(($i+$bytesToRead) > $this->end) {
            $bytesToRead = $this->end - $i + 1;
        }
        $data = fread($this->stream, $bytesToRead);
        echo $data;
        flush();
        $i += $bytesToRead;
    }
}

新的流功能:

function stream()
{
    //added a time limit for safe-guarding
    set_time_limit(3);
    echo fread($this->stream, $this->offset);
    flush();
}
4

1 回答 1

4

假设你有一个 1M 字节的视频当你浏览器第一次请求视频时,它会发送这样的标题

Host:localhost
Range:bytes=0-

范围标头bytes=0-意味着浏览器要求服务器返回,直到它可以返回,即。没有指定结束位置

对此服务器通常会回复除最后一个字节之外的整个文件以保留范围上下文

Accept-Ranges:bytes
Content-Length:99999
Content-Range:bytes 0-99999/1000000

现在假设您的视频下载到 30%,然后您寻求 70%,然后浏览器将请求部分标题是这样的

Host:localhost
Range:bytes=700000-

然而,该元素似乎只从我的服务器请求结束范围,

你可以看到你错误地推断它是视频部分的起始位置

现在服务器可能会回复

Accept-Ranges:bytes
Content-Length:300000
Content-Range:bytes 700000-99999/1000000

请注意Content-Range,它明确说明了文件的哪个部分。所以我猜您的服务器没有发送此信息并且浏览器被窃听。有时mime-types也会导致问题尝试使用文件的确切mimetype,例如Content-Type: video/mp4。如果使用Content-Type: application/octet-stream则可能会导致压缩,从而禁用范围标头

于 2017-01-07T15:11:15.437 回答