HTML5 video element not requesting end Range

6.9k views Asked by At

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.

Range request 1

Range request 2

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.

Full range request history

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();
}
1

There are 1 answers

2
Vinay On

Suppose you have a video of 1M bytes When you browser request for video the first time it will send headers like this

Host:localhost
Range:bytes=0-

Range header bytes=0- means browser is asking server to return till whatever it can return ie. no end position is specified

To this server would usually reply with whole file except last byte to preserve the range context

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

Now suppose your video is downloaded till 30% and you seek to 70% then browser will request that part header would be like this

Host:localhost
Range:bytes=700000-

It seems however that the element only request the end Range from my server,

You can see you inferred wrongly it's the starting position of video part

Now server might reply like

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

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 like Content-Type: video/mp4.If you use Content-Type: application/octet-stream then might cause compression which would disabled range headers