BRO*_*HOM 4 html javascript php http-headers http-range
我有一个<video>and<audio>元素,它通过范围请求从我的服务器加载文件(mp4、mp3,无关紧要)。
然而,该元素似乎只从我的服务器请求结束范围,并从那里开始尝试直接从字节 0 流到末尾,导致播放器陷入“下载循环”,这使得浏览器暂停所有内容其他操作直至下载完成。
有谁知道这个问题的解决方案?例如,我是否必须使我的流请求有一个实际的结束content length或accept-ranges?
这是来自 Chrome 的完整请求列表,在底部您可以看到对该 url 的请求view?watch=v__AAAAAA673pxX一直处于待处理状态,基本上直到element.
简而言之:在使用http-range请求时,html5 元素会陷入下载循环,并导致所有其他请求保持“待处理”状态。
更新
该问题已在服务器端得到解决。
虽然原始流函数实际上会输出每个字节,但我修改了代码以仅输出实际缓冲区的大小。这迫使系统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;
}
}
Run Code Online (Sandbox Code Playgroud)
新的流函数:
function stream()
{
//added a time limit for safe-guarding
set_time_limit(3);
echo fread($this->stream, $this->offset);
flush();
}
Run Code Online (Sandbox Code Playgroud)
假设你有一个 1M 字节的视频,当你浏览器第一次请求视频时,它会发送这样的标头
Host:localhost
Range:bytes=0-
Run Code Online (Sandbox Code Playgroud)
范围标头bytes=0-意味着浏览器要求服务器返回,直到它可以返回任何内容为止。没有指定结束位置
对此服务器通常会回复除最后一个字节之外的整个文件,以保留范围上下文
Accept-Ranges:bytes
Content-Length:99999
Content-Range:bytes 0-99999/1000000
Run Code Online (Sandbox Code Playgroud)
现在假设您的视频已下载到 30%,而您希望下载到 70%,那么浏览器将请求该部分标头如下所示
Host:localhost
Range:bytes=700000-
Run Code Online (Sandbox Code Playgroud)
然而,该元素似乎只从我的服务器请求结束范围,
你可以看到你错误地推断出这是视频部分的起始位置
现在服务器可能会回复如下
Accept-Ranges:bytes
Content-Length:300000
Content-Range:bytes 700000-99999/1000000
Run Code Online (Sandbox Code Playgroud)
请注意Content-Range,它明确告诉了文件的哪个部分。所以我猜测您的服务器没有发送此信息并且浏览器被窃听。有时 mime 类型也会导致问题尝试使用文件的确切 mime 类型,例如Content-Type: video/mp4。如果您使用Content-Type: application/octet-streamthen 可能会导致压缩,从而禁用范围标头