Playing Video - Server is not correctly configured - 12939

核能气质少年 提交于 2019-12-06 13:32:29

To wrap up, this solved my problem:

  • Placed this to VideoController:

    public function streamVideo() 
    {
      $video_path = 'somedirectory/somefile.mp4';
      $stream = new VideoStream($video_path);
      $stream->start(); 
    }
    
  • and then created a file in app > helpers > VideoStream.php:

     <?php
     {
         private $path = "";
         private $stream = "";
         private $buffer = 102400;
         private $start  = -1;
         private $end    = -1;
         private $size   = 0;
    
         function __construct($filePath) 
         {
             $this->path = $filePath;
         }
    
         /**
          *      * Open stream
          *           */
         private function open()
         {
             if (!($this->stream = fopen($this->path, 'rb'))) {
                 die('Could not open stream for reading');
             }
    
         }
    
         /**
          *      * Set proper header to serve the video content
          *           */
         private function setHeader()
         {
             ob_get_clean();
             header("Content-Type: video/mp4");
             header("Cache-Control: max-age=2592000, public");
             header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT');
             header("Last-Modified: ".gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT' );
             $this->start = 0;
             $this->size  = filesize($this->path);
             $this->end   = $this->size - 1;
             header("Accept-Ranges: 0-".$this->end);
    
             if (isset($_SERVER['HTTP_RANGE'])) {
    
                 $c_start = $this->start;
                 $c_end = $this->end;
    
                 list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
                 if (strpos($range, ',') !== false) {
                     header('HTTP/1.1 416 Requested Range Not Satisfiable');
                     header("Content-Range: bytes $this->start-$this->end/$this->size");
                     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('HTTP/1.1 416 Requested Range Not Satisfiable');
                     header("Content-Range: bytes $this->start-$this->end/$this->size");
                     exit;
                 }
                 $this->start = $c_start;
                 $this->end = $c_end;
                 $length = $this->end - $this->start + 1;
                 fseek($this->stream, $this->start);
                 header('HTTP/1.1 206 Partial Content');
                 header("Content-Length: ".$length);
                 header("Content-Range: bytes $this->start-$this->end/".$this->size);
             }
             else
             {
                 header("Content-Length: ".$this->size);
             }  
    
         }
    
         /**
          *      * close curretly opened stream
          *           */
         private function end()
         {
             fclose($this->stream);
             exit;
         }
    
         /**
          *      * perform the streaming of calculated range
          *           */
         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;
             }
         }
    
         /**
          *      * Start streaming video content
          *           */
         function start()
         {
             $this->open();
             $this->setHeader();
             $this->stream();
             $this->end();
         }
     }
    

Source: http://laravel.io/forum/10-06-2014-streaming-video-files-with-laravel

I ran into a problem similar to this one, but your case is going to take a bit more configuration.

The headers for iOS need to be set appropriately using range requests, and the only way I was able to do that for all browsers was by reworking this gist to what I needed.

In my case, I did something like this in Laravel:

//Video controller
...
public function showVideo($id){
    $video = Video::find($id);
    return $this->videoService->stream($video);
}

//Video Service
namespace App\Services\VideoService;
use Illuminate\Routing\ResponseFactory as Response;
use App\Models\Video;
class VideoService implements VideoServiceInterface
{
    protected $response;
    protected $video;
    private $stream = "";
    private $buffer = 102400;
    private $start  = -1;
    private $end    = -1;
    private $size   = 0;
    public function __construct(Response $response){
        $this->response = $response;
    }
    public function stream(Video $video){
        $this->video = $video;
        return $this->response->stream(function(){
            $this->start();
        });
    }
    //Implement the rest of the gist here, renaming where appropriate....
}

Problem is, you're using Lumen which does not support a stream method on the response factory. What you'll need to do is rework the code I gave you to include Symfony's StreamedResponse Object.

If you look at how Laravel does it, you can probably do something like this:

//Video Service
namespace App\Services\VideoService;
use Symfony\Component\HttpFoundation\StreamedResponse as Response;
use App\Models\Video;
class VideoService implements VideoServiceInterface
{
    protected $video;
    private $stream = "";
    private $buffer = 102400;
    private $start  = -1;
    private $end    = -1;
    private $size   = 0;

    public function stream(Video $video){
        $this->video = $video;
        return new Response(function(){
            $this->start();
        });
    }
    //Implement the rest of the gist here, renaming where appropriate....
}

This isn't exact, and it won't work for you out of the box. But this should give you all of the components you need to register your own Service Provider and apply this appropriately to your own use-case.

Good luck.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!