I have a situation that has me stumped so I'm looking for any help I can get.
I have a iOS App that uses MPMoviePlayerViewController to play M4V Video Files managed by a Laravel 5 site.
The video files play perfectly fine (in iOS) if they are directly downloaded from the Laravel 5 /public folder. However, I'm normally storing and serving the Video Files from Laravel 5's Storage Facade as I'm eventually going to use S3 and elastic transcoder.
This works in FireFox with the QuickTime browser plugin, VLC, and other streaming video clients, but not our iOS App.
As far as I can tell the MPMoviePlayerViewController is being picky about how the HTTP Response is being formatted. I have tried StreamedResponse, but that does not seem to help.
So for example the following URL that pulls the file directly from the /public folder works fine from iOS:
http://172.16.160.1/video_ae9a7da0efa211e4b115f73708c37d67.m4v
But if I use Laravel 5 to pull the file from Storage with this URL iOS will not play it.
http://172.16.160.1/api/getfile/f444b190ef5411e4b7068d1890d109e8/video_ae9a7da0efa211e4b115f73708c37d67.m4v
Note iOS does not provide any meaningful errors, to help debug this, but I'm positive its how my HTTP Response is being made by Laravel 5.
Here is my Route:
Route::get('myapi/getfile/{filename?}', 'APIController@getfile')->where('filename', '(.*)');
Here is my Controller:
public function getfile($filename)
{
return $api = API::getfile($filename);
}
Here is my Model:
public static function getfile($filename) {
$file = Storage::disk('local')->get('Files/'.$filename);
return (new Response($file, 200))->header('Content-Type', 'video/mp4');
}
If I left out any supporting info please let me know and I'll post it. My next step may be to setup Wireshark testbed and see what the handshake looks like.
Thanks in advance for the help. :-)
It looks like I have the answer to my own question. The underlying cause was that Laravel 5 does not natively support HTTP byte-range requests when serving files.
This post located here got me on the right track:
MPMoviePlayerPlaybackDidFinishNotification is called immediately
I then found two posts on doing this Laravel 5:
http://laravel.io/forum/09-23-2014-how-to-support-http-byte-serving-in-file-streams
https://gist.github.com/m4tthumphrey/b0369c7bd5e2c795f6d5
The only draw back is I can't use the Storage Facade to directly access the files as streams. So this solution can only be used for files located on the local filesystem.
I know this is an old post, but I ended up needing to stream a video in Laravel from S3 to a player that required HTTP_RANGE support. I put this together (after reading many threads). It should support all disks() you define in Laravel.
I used the class below, placed at App/Http/Responses. To use this class, create a method that does this (this would be the content of your getFile method):
I just pointed my video player's src at a route for that method and success!
S3FileStream.php: