Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP VideoStream class for HTML5 video streaming
<?php
/**
* 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();
}
}
@annopnod

This comment has been minimized.

Copy link

commented Jul 15, 2014

line 39: header("Content-Type: video/mp4");
cannot play .webm file format

you should add:

$ext = strtolower(pathinfo($this->path, PATHINFO_EXTENSION));
switch ($ext)
{
case "mp4":
header("Content-Type: video/mp4");
break;
case "webm":
header("Content-Type: video/webm");
break;
}

@basicssm

This comment has been minimized.

Copy link

commented Oct 17, 2014

I play only 40 second of video?

Why?

@ziggi

This comment has been minimized.

Copy link

commented May 31, 2015

Very useful. Thank you.

@scipper

This comment has been minimized.

Copy link

commented Jun 2, 2015

Very nice! solved my problems :)

@dirkx

This comment has been minimized.

Copy link

commented Sep 1, 2015

May be an idea to add a if(connection_aborted()) near line 104 or as part of the while().

@elangodhilipan

This comment has been minimized.

Copy link

commented Sep 4, 2015

all type video formats are not supported in this code... so please any body help me for all types of video supported streaming code..

@NguyenTungs

This comment has been minimized.

Copy link

commented Oct 23, 2015

Very nice! But The user reload video when streaming ...

@sadiq810

This comment has been minimized.

Copy link

commented Dec 28, 2015

too much helpful ,thanks alot.....

@harish40

This comment has been minimized.

Copy link

commented Feb 1, 2016

How to use the code & where to replace the video path plzz let me know

@nalmada

This comment has been minimized.

Copy link

commented Mar 4, 2016

@ranacseruet
works great !!
do you have the same thing for players like VLC and DivX ?

@ghost

This comment has been minimized.

Copy link

commented Mar 8, 2016

Thank you!

@Lixus

This comment has been minimized.

Copy link

commented Mar 10, 2016

@ranacseruet Thanks for this script! I just noticed that video streaming with this does not work on Android 5 and 6 devices... Any ideas?

@jadrovski

This comment has been minimized.

Copy link

commented Jun 2, 2016

Thank you, very nice solution

@lynxfg

This comment has been minimized.

Copy link

commented Jul 29, 2016

Very nice class !
But the url with http doesn't work :
$stream = new VideoStream(".http://www.exemple.com/video.mp4");
i need a help.
thanks

@inanbayram

This comment has been minimized.

Copy link

commented Sep 6, 2016

@ranacseruet It's possible to stream multiple video files in one php script?

$stream1 = new VideoStream($file1);
$stream1->start();

$stream2 = new VideoStream($file2);
$stream2->start();

If I try the following code, the script is just serving the first video file. Of course I removed the exit's in the class

@ImSeaWorld

This comment has been minimized.

Copy link

commented Oct 8, 2016

@annopnod Why are you making an extra variable?

Turn this:
$ext = strtolower(pathinfo($this->path, PATHINFO_EXTENSION)); switch ($ext) { etc etc

Into this:
switch (strtolower(pathinfo($this->path, PATHINFO_EXTENSION))) { etc etc

You are never going to use $ext again. No point in adding variables that are not going to be used.

EDIT: A better way you could do this, is use an array. Line 39 with the Content-Type header can be turned into a "one-liner".

I added on line 16, the video formats allowed for html(could be more than listed):
private $videoFormats = array("mp4"=>"video/mp4", "webm"=>"video/webm", "ogg"=>"video/ogg");

On line 39 or the Content-Type line I replaced-
This: header("Content-Type: video/mp4");
With this: header("Content-Type: ".($this->videoFormats[strtolower(pathinfo($this->path, PATHINFO_EXTENSION))]));

@wayneworkman

This comment has been minimized.

Copy link

commented Nov 29, 2016

I would like to use this code in a GNU GPLv3 licensed project. Can you please license this code as GNU GPLv3 ?

@gkandemi

This comment has been minimized.

Copy link

commented Dec 28, 2016

Hello,

how to use this class in codeigniter? I tried but I didn't response.

Regards
Gokhan

@mwichary

This comment has been minimized.

Copy link

commented Feb 13, 2017

This basically just saved my life. Thank you.

@acoudray

This comment has been minimized.

Copy link

commented Feb 19, 2017

Hello,

This is a really awesome class you've done here. But I am asking myself if there is a way to find when the video ends streaming ? Thank you a lot.

@lk77

This comment has been minimized.

Copy link

commented Jul 6, 2017

Hello,

the seeking don't working on chrome.

I think you need to change line 48 :
header("Accept-Ranges: 0-".$this->end);
by
header("Accept-Ranges: bytes 0-".$this->end);

@reszko

This comment has been minimized.

Copy link

commented Jul 6, 2017

Hi. Add this statement in stream method before while: session_write_close(). Without it, the browser freezes when a file is streaming when you make new requests, like click to go to another page for example. Before I use session_write_close(), a new request only worked in Firefox. In another browsers all new requests make browser keeps loading until the stream finishes.

@petermajewskicom

This comment has been minimized.

Copy link

commented Sep 19, 2017

If you're using PHP5+

remove Line 76 (fseek($this->stream, $this->start);)

Line 109 change to $data = @stream_get_contents($this->stream, $bytesToRead, $i);

tested on Chrome, Safari and FF

@ConstantinFF

This comment has been minimized.

Copy link

commented Oct 6, 2017

Is there an option to stream multiple video files one after the other, like it is for audio files?

@AlexandrBabich

This comment has been minimized.

Copy link

commented Oct 13, 2017

Hello guys. I had same error in IE11. To solve this issue you need add header("Accept-Ranges: bytes"); after 83 string.
This header is important for IE browsers.

@toddpage

This comment has been minimized.

Copy link

commented Jan 30, 2018

It only plays 2 - 4 seconds of the video on both desktop and iphone. But seems to still download the file.

@vikash2567

This comment has been minimized.

Copy link

commented Feb 14, 2018

I have used the above code in my website. When i refresh the page again and again then video play from starting, this is not a video live streaming. How to implement the video live streaming please tell me?

@glennricster

This comment has been minimized.

Copy link

commented Apr 18, 2018

I don't understand what the point of this is. Perhaps I am missing something. However, rather than using all this heavy machinery to display a video, why not just put the path to the video into the src of the html video element?

@95B

This comment has been minimized.

Copy link

commented Apr 19, 2018

@ImSeaWorld
Couldn't you use this mime_content_type($this->path) to get the MIME content type header dynamically?

header("Content-Type: ".mime_content_type($this->path));

@yisaketsegaye

This comment has been minimized.

Copy link

commented Apr 21, 2018

Thank you that was so helpfull

@rahultrivedi20

This comment has been minimized.

Copy link

commented Jun 4, 2018

My Video is 285 MB. I am trying to play using video streaming from aws server. It is playing directly on aws s3 server. But not able to play directly from video streaming.

@irfanzsheikh

This comment has been minimized.

Copy link

commented Sep 13, 2018

Hello I want to load subtitles in it. how can I do it?
I used to load subtitles like this

could you please help me to how would I use this line in your code?
@acislak

This comment has been minimized.

Copy link

commented Oct 11, 2018

Will this script stop streaming if close the player? I have a suspicion that it will output the data until the end of file is reached. Am I correct?

regards

@Umarnisar

This comment has been minimized.

Copy link

commented Nov 26, 2018

video is not working
am using the mp4 format

@TheGamerTag13

This comment has been minimized.

Copy link

commented Dec 3, 2018

Thank you that was so helpfull, but it's possible to play the video in a <\video> element ?

@hamedbaftam

This comment has been minimized.

Copy link

commented Jan 23, 2019

How to prevent this file from being downloaded???

@TripleXchanyein

This comment has been minimized.

Copy link

commented Mar 9, 2019

Thank you very helpfull

@DJ1TJOO

This comment has been minimized.

Copy link

commented Mar 19, 2019

I want to stream a .mp4 but it wont work and gives no error messages

I have this code:
index.php:
<video controls preload="auto" src="http://localhost/videostream/test.php" width="100%"></video>
test.php:

<?php
include_once 'videostream.php';
$stream = new VideoStream("video.mp4");
$stream->start();exit();

videostream.php:
is the lib

Already solved it the mp4 file was to big

@juliogancino

This comment has been minimized.

Copy link

commented Mar 29, 2019

Thank you that was so helpfull, but it's possible to play the video in a <\video> element ?

http://demo.codesamplez.com/html5/video

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.