I have a <video>
and <audio>
element which load a file (mp4, mp3, doesn't matter) from my server via Range requests.
It seems however that the element only request the end Range from my server, and from there on out tries to stream directly from bytes 0 to the end, causing the player to be stuck in a "download loop", which makes the browser suspend all other actions until the download is complete.
Does anyone know a solution to this issue? Do I for example have to make my stream request HAVE an actual end to its content length
or accept-ranges
?
Here's the full request list from Chrome and at the bottom you can see that a request for the url view?watch=v__AAAAAA673pxX
just stays pending, basically until either a new request is placed by the element
.
In a nutshell: html5 elements get stuck in a download loop when using http-range
requests and cause all other requests to stay "pending".
UPDATE
The issue was resolved server-side.
Whereas the original stream function would literally output every byte, I've modified the code to output ONLY the size of the actual buffer. This forces the elements
to make a new request for the remaining data.
An important note here is to return the content-length
, accept-ranges
and content-ranges
that match the file's size, start and ending position in each HTTP RANGE
request.
For future references:
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;
}
}
new stream function:
function stream()
{
//added a time limit for safe-guarding
set_time_limit(3);
echo fread($this->stream, $this->offset);
flush();
}
Suppose you have a video of 1M bytes When you browser request for video the first time it will send headers like this
Range header
bytes=0-
means browser is asking server to return till whatever it can return ie. no end position is specifiedTo this server would usually reply with whole file except last byte to preserve the range context
Now suppose your video is downloaded till 30% and you seek to 70% then browser will request that part header would be like this
You can see you inferred wrongly it's the starting position of video part
Now server might reply like
Note
Content-Range
it explicitly tells what portion of file .So my guess it that your server is not sending this information and browser is getting bugged. Also sometimes mime-types can also cause problems try to use the exact mimetype of your file likeContent-Type: video/mp4
.If you useContent-Type: application/octet-stream
then might cause compression which would disabled range headers