Streaming video - working with 206 header (from php to HTML5)

As usual, it never works for me ...

I am trying to transfer a video and I am doing very well with the code below:

function send_back_video($video_path)
{
    ob_clean();
    $mime = "application/octet-stream"; // The MIME type of the file, this should be replaced with your own.
    $size = filesize($video_path); // The size of the file

    // Send the content type header
    header('Content-type: ' . $mime);

    // Check if it a HTTP range request
    if(isset($_SERVER['HTTP_RANGE']))
    {       
        // Parse the range header to get the byte offset
        $ranges = array_map(
            'intval', // Parse the parts into integer
            explode(
                '-', // The range separator
                substr($_SERVER['HTTP_RANGE'], 6) // Skip the `bytes=` part of the header
            )
        );

        // If the last range param is empty, it means the EOF (End of File)
        if(!$ranges[1]){
            $ranges[1] = $size - 1;
        }

        // Send the appropriate headers
        header('HTTP/1.1 206 Partial Content');
        header('Accept-Ranges: bytes');
        header('Content-Length: ' . ($ranges[1] - $ranges[0])); // The size of the range

        // Send the ranges we offered
        header(
            sprintf(
                'Content-Range: bytes %d-%d/%d', // The header format
                $ranges[0], // The start range
                $ranges[1], // The end range
                $size // Total size of the file
            )
        );

        // It time to output the file
        $f = fopen($video_path, 'rb'); // Open the file in binary mode
        $chunkSize = 8192; // The size of each chunk to output

        // Seek to the requested start range
        fseek($f, $ranges[0]);

        // Start outputting the data
        while(true)
        {

            // Check if we have outputted all the data requested
            if(ftell($f) >= $ranges[1])
            {
                break;
            }

            // Output the data
            echo fread($f, $chunkSize);

            // Flush the buffer immediately
            @ob_flush();
            flush();
        }
    }
    else {
        // It not a range request, output the file anyway
        header('Content-Length: ' . $size);

        // Read the file
        @readfile($file);

        // and flush the buffer
        @ob_flush();
        flush();
    }
}

"So, if that works, what do you need?" - you ask.

As I said, the code does a very good job, BUT there is 1 problem.

If I start playing the video, php will send header('HTTP/1.1 206 Partial Content')and this (video) request will remain open until EOF, which means I FORCED to download the entire video, even if I don’t want to (say, I click on the next video).

My JS removes the video tags (this should be an ABORT request) and creates a new video tag with a new link. Part of ABORT does not occur.

Here you can see the GET example: enter image description here

  • 1st - get the initial video
  • 2nd - play button pressed
  • 3rd - - DOM .

, , . , youtube GET. , GET "", "" . , , .

P.S.

, - , , .

P.P.S.

.

+4

Source: https://habr.com/ru/post/1657674/


All Articles