I use a PHP script to validate video requests before serving them. This script works as expected on the desktop, with Safari and Chrome. But on iOS, I get a broken play button.
I’m sure the video is properly encoded for iPhone/iPad, because when I access it directly, it works as expected.
The relevant PHP code:
$file_name = 'test-video.mp4';
$file_size = (string)(filesize($file_name));
header('Content-Type: video/mp4');
header('Content-Length: '.$file_size);
readfile_chunked($file_name);
exit;
(readfile_chunked() is similar to readfile() but for very large files, found in the comments on the PHP manual page: http://php.net/manual/en/function.readfile.php. In any event, test-video.mp4 is only ~5 MB, which is less than the memory limit — and in this case I actually can substitute in the normal readfile() and produce the exact same behavior.)
The headers I get when I access test-video.mp4 directly are:
Accept-Ranges:bytes
Connection:Keep-Alive
Content-Length:5558749
Content-Type:video/mp4
Date:Sun, 27 Jun 2010 21:02:09 GMT
Etag:"1c04757-54d1dd-489944c5a6400"
Keep-Alive:timeout=10, max=30
Last-Modified:Tue, 22 Jun 2010 01:25:36 GMT
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
The headers from the PHP script are:
Connection:Keep-Alive
Content-Disposition:inline; filename="test-video.mp4"
Content-Length:5558749
Content-Type:video/mp4
Date:Sun, 27 Jun 2010 21:03:32 GMT
Keep-Alive:timeout=10, max=15
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
X-Powered-By:PHP/5.2.13
I’ve tried many different permutations of headers, even matching them exactly to those from a direct request, to no avail.
Has anyone had success serving HTML5 video through PHP, on iOS?
[Note: I would try using X-Sendfile, but the site is on a shared host with very limited access.]
EDIT: I was reading that iOS can be sensitive about file extensions, so I tried setting up a RewriteRule that rewrites MP4 requests back to my original PHP script, but that didn’t help either.
If you are handling it yourself like that, then you will need to handle byte-range requests yourself as well.