HTML5视频元素未请求结束范围

4
我有一个<video><audio>元素,它通过范围请求从我的服务器加载文件(mp4、mp3都可以)。然而,似乎该元素只从我的服务器请求结束范围,然后直接从字节0到结束位置尝试流式传输,导致播放器陷入“下载循环”,使浏览器暂停所有其他操作,直到下载完成。

Range request 1

Range request 2

有人知道如何解决这个问题吗?例如,我是否需要使我的流请求具有实际的content lengthaccept-ranges来终止它?

以下是来自Chrome的完整请求列表,在底部您可以看到对于URL view?watch=v__AAAAAA673pxX的请求仍然处于挂起状态,基本上直到element放置新请求。

Full range request history

简而言之:使用http-range请求时,html5元素会陷入下载循环并导致所有其他请求保持“挂起”状态。
更新:
问题已经在服务器端解决。
原始流函数会输出每个字节,我修改了代码以仅输出实际缓冲区的大小。这迫使elements为剩余数据发出新的请求。
重要的一点是,在每个HTTP RANGE请求中返回与文件大小、起始位置和结束位置匹配的content-lengthaccept-rangescontent-ranges
供将来参考:
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();
}
1个回答

5
假设您有一个大小为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类型也可能会引起问题,请尝试使用您文件的确切MIME类型,例如 Content-Type: video/mp4。如果您使用Content-Type: application/octet-stream,则可能会导致压缩并禁用范围头。

你是对的。不幸的是,提供的代码使用了 while 循环来输出请求数据。我已经修改了代码,只输出缓冲区大小(例如 (1024 * 1024)),这样一旦达到缓冲区大小,输出流就会关闭。这确保了 <video>/<audio> 必须发起新的数据请求,因为提供的数据与 Content-Length 标头不匹配。 - BRO_THOM
这个问题有任何更新吗?我看到Chrome和Firefox发送的范围没有正确的结束,服务器在响应中写入整个文件。提出的使用显式缓冲区的解决方案有效,但看起来像是一个hack。 - Vitaly Tsvetkoff

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