Jun*_*ius 7 php iphone video-streaming ios laravel-5
我有一种情况让我难过,所以我正在寻找任何可以得到的帮助.
我有一个iOS应用程序,它使用MPMoviePlayerViewController播放由Laravel 5站点管理的M4V视频文件.
如果直接从Laravel 5 /公共文件夹下载视频文件,则视频文件可以完美地播放(在iOS中).但是,我通常会从Laravel 5的Storage Facade存储和提供视频文件,因为我最终将使用S3和弹性转码器.
这适用于FireFox与QuickTime浏览器插件,VLC和其他流视频客户端,但不适用于我们的iOS应用程序.
据我所知,MPMoviePlayerViewController对于如何格式化HTTP响应非常挑剔.我尝试过StreamedResponse,但这似乎没有帮助.
因此,例如,直接从/ public文件夹中提取文件的以下URL可以在iOS上正常工作:
http://172.16.160.1/video_ae9a7da0efa211e4b115f73708c37d67.m4v
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用Laravel 5从存储中提取该文件,iOS将无法播放.
http://172.16.160.1/api/getfile/f444b190ef5411e4b7068d1890d109e8/video_ae9a7da0efa211e4b115f73708c37d67.m4v
Run Code Online (Sandbox Code Playgroud)
注意iOS没有提供任何有意义的错误,以帮助调试它,但我很肯定它是如何通过Laravel 5制作我的HTTP响应.
这是我的路线:
Route::get('myapi/getfile/{filename?}', 'APIController@getfile')->where('filename', '(.*)');
Run Code Online (Sandbox Code Playgroud)
这是我的控制器:
public function getfile($filename)
{
return $api = API::getfile($filename);
}
Run Code Online (Sandbox Code Playgroud)
这是我的模型:
public static function getfile($filename) {
$file = Storage::disk('local')->get('Files/'.$filename);
return (new Response($file, 200))->header('Content-Type', 'video/mp4');
}
Run Code Online (Sandbox Code Playgroud)
如果我遗漏了任何支持信息,请告诉我,我会发布.我的下一步可能是设置Wireshark测试平台,看看握手的样子.
在此先感谢您的帮助.:-)
看起来我对自己的问题有了答案.根本原因是Laravel 5在提供文件时本身不支持HTTP字节范围请求.
这篇文章位于这里让我走在正确的轨道上:
立即调用MPMoviePlayerPlaybackDidFinishNotification
然后我发现了两篇关于Laravel 5的帖子:
http://laravel.io/forum/09-23-2014-how-to-support-http-byte-serving-in-file-streams
https://gist.github.com/m4tthumphrey/b0369c7bd5e2c795f6d5
唯一的缺点是我无法使用Storage Facade直接访问文件作为流.因此,此解决方案只能用于位于本地文件系统上的文件.
public static function getfile($filename) {
$size = Storage::disk('local')->size('files/'.$filename);
$file = Storage::disk('local')->get('files/'.$filename);
$stream = fopen($storage_home_dir.'files/'.$filename, "r");
$type = 'video/mp4';
$start = 0;
$length = $size;
$status = 200;
$headers = ['Content-Type' => $type, 'Content-Length' => $size, 'Accept-Ranges' => 'bytes'];
if (false !== $range = Request::server('HTTP_RANGE', false)) {
list($param, $range) = explode('=', $range);
if (strtolower(trim($param)) !== 'bytes') {
header('HTTP/1.1 400 Invalid Request');
exit;
}
list($from, $to) = explode('-', $range);
if ($from === '') {
$end = $size - 1;
$start = $end - intval($from);
} elseif ($to === '') {
$start = intval($from);
$end = $size - 1;
} else {
$start = intval($from);
$end = intval($to);
}
$length = $end - $start + 1;
$status = 206;
$headers['Content-Range'] = sprintf('bytes %d-%d/%d', $start, $end, $size);
}
return Response::stream(function() use ($stream, $start, $length) {
fseek($stream, $start, SEEK_SET);
echo fread($stream, $length);
fclose($stream);
}, $status, $headers);
}
Run Code Online (Sandbox Code Playgroud)