0

I would like to show an mp4 through the video tag and the source URL of the video is a URL to a YII application. I was using Yii:app->request->sendFile before but the video wasn't working on the iPad/iPhone so now I'm trying to send the headers myself using the code below but still not working.

$finfo = finfo_open(FILEINFO_MIME_TYPE);  
$file_path = "video.mp4";
$file_mime_type = finfo_file($finfo, $file_path);
$file_size = filesize($file_path);

header("HTTP/1.1 206 Partial Content");
header("Accept-Ranges: bytes");
header("Content-Type: $file_mime_type");
header("Content-Length: $file_size");
header("Content-Range: bytes 0-".($file_size-1)."/$file_size");
readfile($file_path);
exit;

I even tried to implement the rangeDownload function from http://mobiforge.com/developing/story/content-delivery-mobile-devices but the problem is that the $_SERVER['HTTP_RANGE'] is always null even when the request is coming from an iPhone/iPad.

I also tried this solution here mp4 file through php not playing as html5 video but to no avail again..

The code above works fine for a web browser. Also if I access the .mp4 directly from the iPhone/iPad it works fine too so it is not a problem with the video itself

Any help please?

Community
  • 1
  • 1
hex4
  • 695
  • 2
  • 9
  • 23
  • 4
    why not just do a `header('Location: video.mp4');` ? – cmorrissey Aug 09 '13 at 13:55
  • If `$_SERVER['HTTP_RANGE']` is `NULL`, why do you send a partial content response? Also if you send a partial content response, why do you send the whole file? Also you need to provide the response headers you generate not only the code, but the actual response. HTTP is here btw: http://tools.ietf.org/html/rfc2616 – hakre Aug 14 '13 at 07:35
  • Also try to see, what's happen with tools like Fiddler2. First you can see what happens mp4 in html, then what happens with php and compare HTTP-request headers. – Dima Kurilo Aug 16 '13 at 07:37
  • @cmorrissey, it wouldn't work with a password protected directory. – Jose Manuel Abarca Rodríguez Feb 09 '21 at 17:07

1 Answers1

0

Your problem may be from several reason.
1) You can't create a right video. Try to use a string like this:

c:\utils\ffmpeg\bin\ffmpeg -i MVI_7386.MOV -acodec aac -ac 2 -strict experimental -b:a 160k -s 640x480 -vcodec libx264 -preset slow -profile:v baseline -level 30 -maxrate 10000000 -bufsize 10000000 -b:v 1200k -pix_fmt yuv420p -f mp4 -threads 2 -async 1 -vsync 1 -y video.ipad.mp4

2) I used this answer with small changes for send video via php. Here is my video.php file:

<?php
$path = './video.ipad.mp4';
if (file_exists($path)) {
  $size=filesize($path);
  $fm=@fopen($path,'rb');
  if(!$fm) {
    // You can also redirect here
    header ("HTTP/1.1 404 Not Found");
    die();
  }
  $begin=0;
  $end=$size;
  if(isset($_SERVER['HTTP_RANGE'])) {
    if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i',   
      $_SERVER['HTTP_RANGE'],$matches)){
      $begin=intval($matches[1]);
      if(!empty($matches[2])) {
        $end=intval($matches[2]);
      }
    }
  }
  if($begin>0||$end<$size) header('HTTP/1.1 206 Partial Content');
  else header('HTTP/1.1 200 OK');
  header("Content-Type: video/mp4");
  header('Content-Length:'.($end-$begin));
  header("Content-Range: bytes $begin-$end/$size");
  $cur=$begin;
  fseek($fm,$begin,0);
  while(!feof($fm)&&$cur<$end&&(connection_status()==0)) {
    print fread($fm,min(1024*16,$end-$cur));
    $cur+=1024*16;
    usleep(1000);
  }
  die();
}

And the html is very simple:

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>test</title>
</head>
<body>
    <video controls>
        <source src="./video.php" type="video/mp4">
    </video>
</body>
</html>

You can see what I done here.

P.S. Sorry for video. :) I could not find anoter one.

Community
  • 1
  • 1
Dima Kurilo
  • 2,206
  • 1
  • 21
  • 27
  • Hi Dmitry, thank you for the helpful answer. I have set up everything as you did, but problem is that your demo works on the iPad, but not [the demo on my server](http://www.echteinfach.tv/videos/test4.php). I am using the same PHP script. The headers are nearly the same: My shared-hosting-server sets "Connection: close" instead of "keep-alive", plus I have a "Cache-Control: max-age=2592000". I have gzip disabled, Accept-Ranges enabled. The correct MIME type `video/mp4 .mp4` is set. Can you help me? (PS: I will remove your video from my server when I found the solution, thank you) – Avatar Jun 04 '14 at 13:17
  • Here is a full description of the problem: http://stackoverflow.com/questions/24042894/php-ipad-does-not-play-mp4-videos-delivered-by-php-but-if-accessed-directly-it – Avatar Jun 04 '14 at 17:15
  • @EchtEinfachTV, I don't see the problem with this video: http://www.echteinfach.tv/videos/test4.php I created this page and the first video is test4.php: http://www.kurilo.su/iphone/testvideo1.html Video from http://www.echteinfach.tv/test/ipad/test-headers.php is the second video on my test page and it doesn't work. I tried to place it on my server and it works (third video on my test page). As I see you have Accept-Ranges:bytes header two times. I don't know how you create same header twice. It's not so easy, as I understand. :) But I think it can be a root of the problem. – Dima Kurilo Jun 04 '14 at 17:42
  • Thanks for your reply and for testing the scripts on your server, much appreciated! As I can see the [embedded videos](http://www.kurilo.su/iphone/testvideo1.html) (PHP loaded video files from my server) do not show up on the iPad either. But the third video that you have uploaded onto your server (direct embed works also on my server). # Accept-Ranges is set by htaccess plus by the PHP scripts. I removed it from the htaccess but it did not change anything. My hoster sets the server to "Connection: close", I cannot change it to "keep-alive". Do you think this could be the issue? – Avatar Jun 04 '14 at 17:49
  • Could you try to upload the [PHP scripts](http://stackoverflow.com/questions/24042894/php-ipad-does-not-play-mp4-videos-delivered-by-php-but-if-accessed-directly-it) (replace .php with .txt to download them) to your testing folder? Then we could see if they work on your server or not. Thank you :) – Avatar Jun 04 '14 at 17:56
  • http://www.kurilo.su/iphone/testvideo1.html - last two videos is provided by your code. And it works. It doesn't work with desktop Chrome, but it works on my Android phone. – Dima Kurilo Jun 04 '14 at 18:46
  • I found iPhone and your videos don't work on the iPhone. I can't understad why. I need a device to understand. But I think you should recode the videos first. – Dima Kurilo Jun 04 '14 at 18:52
  • Thanks Dmitry, I checked your test link on the iPad, the videos do not work. I get the striked-through play symbol. Which script are you using for your video1.php? http://www.echteinfach.tv/test/ipad/test-headers.txt or http://www.echteinfach.tv/test/ipad/test-byterange.txt or http://www.echteinfach.tv/test/ipad/test-byterange-2.txt ? – Avatar Jun 05 '14 at 03:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/55108/discussion-between-dmitry-kurilo-and-echt-einfach-tv). – Dima Kurilo Jun 05 '14 at 05:36