HTTP range, streaming, music and audio

I have a website that I use to stream audio files. Mostly MP3 and OGG. Starting from a few months, I have been processing myself (PHP) the paired part (before it was apache2). First, I make the usual 200 OK answer with a chopped binary response of my multimedia audio files (to allocate memory). It works great, but I got infinity on all my audio. According to this question, I updated the streaming content yesterday.

And now I have one of the strangest mistakes I could imagine. My code refactor works fine with MP3, but not with OGG ... Images or zip downloads also work with the class above, and both of them work just fine as before.

Here is my Stream class.

<?php
class Stream extends Response
{
    protected $filepath;
    protected $delete;
    protected $range = ['from' => 0, 'to' => null];

    public function __construct($filePath, $delete = false, $range = NULL)
    {
        $this->delete = $delete;
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $filePath);
        $size = filesize($filePath);

        $this->headers['Content-Type'] = $mimeType;
        $this->headers['Content-Length'] = $size;
        $this->headers['Accept-Ranges'] = 'bytes';
        $this->headers['Content-Transfer-Encoding'] = 'binary';
        unset($finfo, $mimeType);

        $this->code = 200;
        $this->range['to'] = $size - 1;

        if ($range !== NULL) {
            if (preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/i', $range) === false) {
                $this->code = 416;
            } else {
                $ranges = explode(',', substr($range, 6));
                foreach ($ranges as $rangee) {
                    $parts = explode('-', $rangee);
                    $this->range['from'] = intval($parts[0]);
                    $this->range['to'] = intval($parts[1]);

                    if (empty($this->range['to'])) {
                        $this->range['to'] = $size - 1;
                    }
                    if ($this->range['from'] > $this->range['to'] || $this->range['to'] >= $size) {
                        $this->code = 416;
                    }
                }
                $this->code = 206;
            }

        }

        if ($this->code === 416) {
            $this->headers = ['Content-Range' => 'bytes */{' . $size . '}'];
        } elseif ($this->code === 206) {
            $this->headers['Content-Range'] = 'bytes {' . $this->range['from'] . '}-{' . $this->range['to'] . '}/{' . $size . '}';
        }

        $this->filepath = $filePath;
    }

    public function show()
    {
        http_response_code($this->code);

        foreach ($this->headers as $header => $value) {
            header($header . ': ' . $value);
        }

        $file = fopen($this->filepath, 'r');
        fseek($file, $this->range['from']);

        $interval = $this->range['to'] - $this->range['from'];
        $outputBufferInterval = 4 * 1000;

        if ($interval < $outputBufferInterval) {
            $outputBufferInterval = $interval;
        }

        ob_start();
        while ($interval > 0) {
            echo fread($file, $outputBufferInterval);
            $interval -= $outputBufferInterval;
            ob_flush();
        }
        fclose($file);
        ob_end_clean();

        if ($this->delete) {
            unlink($this->filepath);
        }
    }
}

HTTP_RANGE. ,

0

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


All Articles