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

@annopnod annopnod 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

@basicssm basicssm commented Oct 17, 2014

I play only 40 second of video?

Why?

@ziggi

This comment has been minimized.

Copy link

@ziggi ziggi commented May 31, 2015

Very useful. Thank you.

@scipper

This comment has been minimized.

Copy link

@scipper scipper commented Jun 2, 2015

Very nice! solved my problems :)

@dirkx

This comment has been minimized.

Copy link

@dirkx dirkx 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

@elangodhilipan elangodhilipan 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

@NguyenTungs NguyenTungs commented Oct 23, 2015

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

@sadiq810

This comment has been minimized.

Copy link

@sadiq810 sadiq810 commented Dec 28, 2015

too much helpful ,thanks alot.....

@harish40

This comment has been minimized.

Copy link

@harish40 harish40 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

@nalmada nalmada 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

@ghost ghost commented Mar 8, 2016

Thank you!

@Lixus

This comment has been minimized.

Copy link

@Lixus Lixus 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

@jadrovski jadrovski commented Jun 2, 2016

Thank you, very nice solution

@lynxfg

This comment has been minimized.

Copy link

@lynxfg lynxfg 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

@inanbayram inanbayram 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

@ImSeaWorld ImSeaWorld 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

@wayneworkman wayneworkman 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

@gkandemi gkandemi 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

@mwichary mwichary commented Feb 13, 2017

This basically just saved my life. Thank you.

@acoudray

This comment has been minimized.

Copy link

@acoudray acoudray 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

@lk77 lk77 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

@reszko reszko 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

@petermajewskicom petermajewskicom 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

@ConstantinFF ConstantinFF 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

@AlexandrBabich AlexandrBabich 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

@toddpage toddpage 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

@vikash2567 vikash2567 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

@glennricster glennricster 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

@95B 95B 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

@yisaketsegaye yisaketsegaye commented Apr 21, 2018

Thank you that was so helpfull

@rahultrivedi20

This comment has been minimized.

Copy link

@rahultrivedi20 rahultrivedi20 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

@irfanzsheikh irfanzsheikh 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

@acislak acislak 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

@Umarnisar Umarnisar commented Nov 26, 2018

video is not working
am using the mp4 format

@TheGamerTag13

This comment has been minimized.

Copy link

@TheGamerTag13 TheGamerTag13 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

@hamedbaftam hamedbaftam commented Jan 23, 2019

How to prevent this file from being downloaded???

@TripleXchanyein

This comment has been minimized.

Copy link

@TripleXchanyein TripleXchanyein commented Mar 9, 2019

Thank you very helpfull

@DJ1TJOO

This comment has been minimized.

Copy link

@DJ1TJOO DJ1TJOO 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

@juliogancino juliogancino 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

@vtuykom

This comment has been minimized.

Copy link

@vtuykom vtuykom commented Nov 5, 2019

Thank you for this script
I am looking for a solution to can start and stop de streaming like I would decide.
If I have a video of 50s and I would see a piece of this video
For example between the 30de second and de 33de second.
Can somebody my help please ?
Thank you
Alain

@ericol

This comment has been minimized.

Copy link

@ericol ericol commented Nov 16, 2019

A while ago, I was looking for a stream server. I really did try to find a solution for that, to no avail.

Lo and behold, today it occurred to me that "may be" there was a script available that would cover my needs. So, I did search for one first in PHP (I can handle python, but I'm a lot more proficient in PHP) and I found this.

I gotta say, man. What a surprise.

This one works flawlessly, and covered completely my needs (that happen to be quite special).

Dude, I'm incredible grateful for this.

@Emilio2233

This comment has been minimized.

Copy link

@Emilio2233 Emilio2233 commented Mar 4, 2020

Dear Ranacseruet

If the streaming starts i cannot leave the page until the video has loaded completely. Is there a way to stop the streaming if a visitor wants to leave the page ? (It happens in chrome, in firefox you can leave the page)

@BlackIQ

This comment has been minimized.

Copy link

@BlackIQ BlackIQ commented Apr 21, 2020

Very useful. Thank you.

how did you use that ?
I have this script in a folder name "live" .
So when I open it -> 127.0.0.1/live , it does not show anything !
where should I put video ?
my video is in that folder too .
Please help me !

@dragona

This comment has been minimized.

Copy link

@dragona dragona commented May 5, 2020

Very useful. Thank you.

how did you use that ?
I have this script in a folder name "live" .
So when I open it -> 127.0.0.1/live , it does not show anything !
where should I put video ?
my video is in that folder too .
Please help me !

1- Download the DownloadStream.php
2- Save it in the root of your server (online or local)
3- Create a second file and name it "index.php"
4- Copy the following code in your "index.php"
<?php include "VideoStream.php"; $filePath = "demo.mp4"; $stream = new VideoStream($filePath); $stream->start();

5- Copy and paste the video you would like to stream in the same root (same location as your VideoStream and index files)
6- Rename the video file to be "demo.mp4"

@kezern

This comment has been minimized.

Copy link

@kezern kezern commented May 20, 2020

I'm having some issues.
Allowed memory size of 134217728 bytes exhausted (tried to allocate 307971432 bytes)
I have already increased the memory_limit parameter, but it still does not work....

@saikatstutorial

This comment has been minimized.

Copy link

@saikatstutorial saikatstutorial commented Aug 17, 2020

Can someone put an example on how to stream aws S3 video using this VideoStreamer class?

@InstanceOfMichael

This comment has been minimized.

Copy link

@InstanceOfMichael InstanceOfMichael commented Sep 22, 2020

I am using the <video> tag (only test chrome so far) and my videos keep getting stuck "buffering" randomly starting around 40s up to 3 minutes. My sample video isn't much longer. I've never been able to finish watching a video. Manual seeking works (in general and when stuck buffering) but if I try to watch it straight through it always gets stuck buffering.

@rorenzo

This comment has been minimized.

Copy link

@rorenzo rorenzo commented Dec 15, 2020

hi, I'm using your code, I made just a little mod. It work very well on windows (all browser), but in MACOS (all browser) the video does not play. any idea? thanks

@lizardpeter

This comment has been minimized.

Copy link

@lizardpeter lizardpeter commented Jan 23, 2021

Is there a way to use this and prevent users from downloading the video? The video can be downloaded by just right clicking after the entire video has been played. I am looking for a way to prevent it from being downloaded (like streaming services use).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment