Stream mp4 through php file gradually

I am working on a safer streaming method for our video player. Since each file requires special authentication by token, and also only each boot token is downloaded once, I launch MP4 through the php container. This works fine inside the HTML5 tag and does not allow users to download the source easily .

I am adapting the code here

<?php include('...'); //include site functions /* Here I connect to the database, and retrieve the location of the video which is returned as $video = "http://domain.tld/folder/file.mp4" This has been removed for this SO example. */ $file = $video; $fp = @fopen($file, 'rb'); $head = array_change_key_case(get_headers($file, TRUE)); $size = $head['content-length']; //$size = filesize($file); // File size $length = $size; // Content length $start = 0; // Start byte $end = $size - 1; // End byte header('Content-type: video/mp4'); //header("Accept-Ranges: 0-$length"); header("Accept-Ranges: bytes"); if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $start; $c_end = $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 $start-$end/$size"); exit; } if ($range == '-') { $c_start = $size - substr($range, 1); }else{ $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size; } $c_end = ($c_end > $end) ? $end : $c_end; if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $start-$end/$size"); exit; } $start = $c_start; $end = $c_end; $length = $end - $start + 1; fseek($fp, $start); header('HTTP/1.1 206 Partial Content'); } header("Content-Range: bytes $start-$end/$size"); header("Content-Length: ".$length); $buffer = 1024 * 8; while(!feof($fp) && ($p = ftell($fp)) <= $end) { if ($p + $buffer > $end) { $buffer = $end - $p + 1; } set_time_limit(0); echo fread($fp, $buffer); flush(); } fclose($fp); exit(); ?> 

Now there are problems, because I want you to be able to search for videos. Skipping to an area in a video that has not been uploaded breaks the <video> (and chrome).

I would suggest that since the HTML5 player searches in seconds and PHP loads in bytes, this cannot be done. That is why I ask here.

What can I do (if any) to ensure progressive transmission?
Is there a more suitable container format that I could use that would serve the same purpose?

+6
source share
5 answers

I think you have a conceptual failure. You process the mp4 file as if it were a "raw data file." I'm trying to explain myself.

Imagine that you have a text file and you want to get characters from position X. You can open the file, move the cursor to the correct position and then read the byte in your text. This will work fine.

But now the image you want to do the same, but with a word processor file. Do you expect the same results? No, because you have a lot of metadata in the file that prevents you from doing this.

Your problem is basically the same. You must consider the file format, manage the file using the libraries intended for it, or do it yourself.

Another option is to work with raw data files, but in the case of video files, these will be really large files.

I hope I helped you.

+1
source

In addition to what dlopez said, I recommend using a third-party progressive download solution with search capabilities (AKA pseudo-stream). You can take a look at the PD solutions listed on Wikipedia: https://en.wikipedia.org/wiki/Progressive_download

Most of them can also interfere with the protection of hotlink videos.

+4
source

You cannot use fseek (5654) if you use the file path from http://example.com ...... you should use c: /file/abc.mp4 instead. This may solve your problem ...

0
source

I had a similar problem. Using stream_get_content($fp, $start) instead of fseek fixed the problem. I was able to get the video for streaming on all browsers, and searching (or skipping) throughout the video worked without problems.

0
source

Fully functional code

 $file = "z.mp4"; $length= filesize($file); $offset = 0; $f = fopen($file, 'r'); stream_get_contents($f, $offset); $pos = 0; while($pos < $length){ $chunk = min($length-$pos, 1024*8); echo fread($f, $chunk); flush(); ob_flush(); $pos += $chunk; } 
0
source

All Articles