Skip to content

Instantly share code, notes, and snippets.

@vluzrmos
Forked from ranacseruet/VideoStream.php
Last active June 22, 2025 08:42
Show Gist options
  • Select an option

  • Save vluzrmos/d5682ad426525196d069 to your computer and use it in GitHub Desktop.

Select an option

Save vluzrmos/d5682ad426525196d069 to your computer and use it in GitHub Desktop.
<?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();
}
}
@MohammedAl-Mahdawi

Copy link
Copy Markdown

Thank you

@andruxnet

Copy link
Copy Markdown

This doesn't work with .mov videos, does it?

@bobper

bobper commented Aug 9, 2017

Copy link
Copy Markdown

this is not working for me
http://sargar.ir/learning/film/19

@AlexandrBabich

AlexandrBabich commented Oct 13, 2017

Copy link
Copy Markdown

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.

@chrispito

Copy link
Copy Markdown

Thank you very much!!!!!!

@Smruti325

Copy link
Copy Markdown

thanks

@MMTE

MMTE commented Mar 9, 2020

Copy link
Copy Markdown

Thanks so much.
I used that in my project.
working perfectly

@belltzel

Copy link
Copy Markdown

Thank you! It was very helpful! !!

@chintanbawa

Copy link
Copy Markdown

Thank you so much. It helped me alot.

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