diff --git a/src/Download/Framework/Controller/ApiController.php b/src/Download/Framework/Controller/ApiController.php index d3dee6b..1a88608 100644 --- a/src/Download/Framework/Controller/ApiController.php +++ b/src/Download/Framework/Controller/ApiController.php @@ -4,6 +4,7 @@ namespace App\Download\Framework\Controller; use App\Download\Action\Input\DownloadMediaInput; use App\Download\Framework\Repository\DownloadRepository; +use App\Download\Stream; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -56,4 +57,17 @@ class ApiController extends AbstractController return $this->json(['status' => 200, 'message' => 'Added to Queue']); } + + #[Route('/stream', 'app_stream', methods: ['GET'])] + public function streamVideo() + { + $stream = new Stream( + 'https://torrentio.strem.fun/realdebrid/QYYBR7OSQ4VEFKWASDEZ2B4VO67KHUJY6IWOT7HHA7ATXO7QCYDQ/e8b22517328a9704bf8400b8b98cfc22836ad1e4/null/3/Ted.2012.UNRATED.1080p.BluRay.x265-RARBG.mp4', + [ + + ] + ); + + return $stream->start(); + } } \ No newline at end of file diff --git a/src/Download/Stream.php b/src/Download/Stream.php new file mode 100644 index 0000000..f73bd51 --- /dev/null +++ b/src/Download/Stream.php @@ -0,0 +1,137 @@ +path = $filePath; + $this->httpString = isset($options['is_https']) ? (($options['is_https'] == true) ? "HTTPS/1.1" : "HTTP/1.1") : "HTTP/1.1"; + $this->size = isset($options['video_size']) ? $options['video_size'] : $this->size; + $this->buffer = isset($options['video_buffer']) ? $options['video_buffer'] : $this->buffer; + $this->contentType = isset($options['content_type']) ? $options['content_type'] : $this->contentType; + $this->cacheControl = isset($options['cache_control']) ? $options['cache_control'] : $this->cacheControl; + $this->expires = isset($options['expires']) ? $options['expires'] : gmdate('D, d M Y H:i:s', time()+2592000).' GMT'; + $this->lastModified = isset($options['last_modified']) ? $options['last_modified'] : gmdate('D, d M Y H:i:s', @filemtime($this->path)).' GMT'; + } + + private function open(){ + if (!($this->stream = fopen($this->path, 'rb'))) { + die('Could not open stream for reading'); + } + } + + private function setHeader(){ + // if (isset($_SERVER['RANGE'])) { + // print_r($_SERVER); + // die(); + // } + + ob_get_clean(); + header("Content-Type: ".$this->contentType); + header("Cache-Control: ".$this->cacheControl); + header("Expires: ".$this->expires); + header("Last-Modified: ".$this->lastModified); + $this->start = 0; + $this->size = ($this->size == null || $this->size <= 0) ? $this->getContentLengthFromURL($this->path) : $this->size; + $this->end = $this->size - 1; + + header("Accept-Ranges: bytes"); + + + if (isset($_SERVER['HTTP_RANGE'])) { + // header("Accept-Ranges: 0-".$this->end); + + $c_start = $this->start; + $c_end = $this->end; + + list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); + if (strpos($range, ',') !== false) { + header($this->httpString.' 416 Requested Range Not Satisfiable'); + header("Content-Range: bytes ".$this->start."-".$this->end."/".$this->size); + header("X-ERROR-ERROR: TRUE"); + exit; + } + if ($range == '-') { + $c_start = $this->size - substr($range, 1); + }else{ + $range = explode('-', $range); + $c_start = $range[0]; + + $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; + } + $c_end = ($c_end > $this->end) ? $this->end : $c_end; + if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) { + header($this->httpString.' 416 Requested Range Not Satisfiable'); + header("Content-Range: bytes ".$this->start."-".$this->end."/".$this->size); + header("X-ERROR-ERROR: TRUE"); + exit; + } + $this->start = $c_start; + $this->end = $c_end; + $length = $this->end - $this->start + 1; + fseek($this->stream, $this->start, SEEK_CUR); + header($this->httpString.' 206 Partial Content', true, 206); + header("Content-Length: ".$length); + header("Content-Range: bytes ".$this->start."-".$this->end."/".$this->size); + } + else + { + header("Accept-Ranges: bytes"); + header("Content-Length: ".$this->size); + } + + } + + private function end(){ + fclose($this->stream); + exit; + } + + private 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; + } + } + + function start(){ + $this->open(); + $this->setHeader(); + $this->stream(); + $this->end(); + } + + function getContentLengthFromURL($url){ + $arrayHeaders = get_headers($url,true); + $arrayHeaders = array_change_key_case($arrayHeaders, CASE_LOWER); + if(isset($arrayHeaders['content-length'])){ + if(is_numeric($arrayHeaders['content-length']) && $arrayHeaders['content-length'] > 0){ + return $arrayHeaders['content-length']; + } + } + return null; + } + +} \ No newline at end of file