Skip to content

Instantly share code, notes, and snippets.

@killtw
Forked from vluzrmos/App_Http_VideoStream.php
Created January 11, 2016 11:52
Show Gist options
  • Select an option

  • Save killtw/dba0e79504b2e0365b5b to your computer and use it in GitHub Desktop.

Select an option

Save killtw/dba0e79504b2e0365b5b to your computer and use it in GitHub Desktop.

Revisions

  1. @vluzrmos vluzrmos revised this gist Jul 18, 2015. 1 changed file with 2 additions and 117 deletions.
    119 changes: 2 additions & 117 deletions App_Http_VideoStream.php
    Original file line number Diff line number Diff line change
    @@ -6,124 +6,9 @@
    * Description of VideoStream
    *
    * @author Rana
    * @link https://gist.github.com/ranacseruet/9826293
    * @link https://gist.github.com/vluzrmos/d5682ad426525196d069
    */
    class VideoStream
    {
    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();
    }
    /* Visite o link https://gist.github.com/vluzrmos/d5682ad426525196d069 para ver o conteúdo desse arquivo. */
    }
  2. @vluzrmos vluzrmos revised this gist Jul 18, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion App_Http_VideoStream.php
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@
    * Description of VideoStream
    *
    * @author Rana
    * @link http://codesamplez.com/programming/php-html5-video-streaming-tutorial
    * @link https://gist.github.com/ranacseruet/9826293
    */
    class VideoStream
    {
  3. @vluzrmos vluzrmos revised this gist Jul 18, 2015. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions App_Http_routes.php
    Original file line number Diff line number Diff line change
    @@ -15,9 +15,9 @@
    if (file_exists($filePath = $videosDir."/".$filename)) {
    $stream = new \App\Http\VideoStream($filePath);

    $stream->start();

    return;
    return response()->stream(function() use ($stream) {
    $stream->start();
    });
    }

    return response("File doesn't exists", 404);
  4. @vluzrmos vluzrmos revised this gist Jul 18, 2015. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions resources_views_player.blade.php
    Original file line number Diff line number Diff line change
    @@ -8,12 +8,18 @@
    </head>
    <body>

    <video id="example_video_1" class="video-js vjs-default-skin"
    controls preload="auto" width="640" height="264">
    <video id="example_video_1" class="video-js vjs-default-skin vjs-big-play-centered"
    controls preload="auto" height="600" width="980">

    <source src="{{url($video)}}" type="{{$mime}}" />
    </video>

    <script src="//vjs.zencdn.net/4.12/video.js"></script>

    <script>
    videojs(document.getElementById('example_video_1'), {}, function() {
    // This is functionally the same as the previous example.
    });
    </script>
    </body>
    </html>
  5. @vluzrmos vluzrmos created this gist Jul 18, 2015.
    129 changes: 129 additions & 0 deletions App_Http_VideoStream.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,129 @@
    <?php

    namespace App\Http;

    /**
    * Description of VideoStream
    *
    * @author Rana
    * @link http://codesamplez.com/programming/php-html5-video-streaming-tutorial
    */
    class VideoStream
    {
    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();
    }
    }
    24 changes: 24 additions & 0 deletions App_Http_routes.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    <?php

    Route::get('/player', function () {
    $video = "video/os_simpsons_s25e22_720p.mp4";
    $mime = "video/mp4";
    $title = "Os Simpsons";

    return view('player')->with(compact('video', 'mime', 'title'));
    });

    Route::get('/video/{filename}', function ($filename) {
    // Pasta dos videos.
    $videosDir = base_path('resources/assets/videos');

    if (file_exists($filePath = $videosDir."/".$filename)) {
    $stream = new \App\Http\VideoStream($filePath);

    $stream->start();

    return;
    }

    return response("File doesn't exists", 404);
    });
    19 changes: 19 additions & 0 deletions resources_views_player.blade.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    <!doctype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>{{$title}}</title>

    <link href="//vjs.zencdn.net/4.12/video-js.css" rel="stylesheet">
    </head>
    <body>

    <video id="example_video_1" class="video-js vjs-default-skin"
    controls preload="auto" width="640" height="264">

    <source src="{{url($video)}}" type="{{$mime}}" />
    </video>

    <script src="//vjs.zencdn.net/4.12/video.js"></script>
    </body>
    </html>