Laravel从storage目录读取视频流无法正常播放怎么解决?
可行解决方案
核心错误原因
- 逻辑位置错误:视频流属于HTTP响应逻辑,不可放在模型访问器中。访问器返回的内容会被直接填充到
<source>的src属性中,而非作为独立的资源响应返回,导致HTML结构被二进制视频内容打乱 - 路径错误:
Storage::disk('local')的根目录默认指向storage/app,路径填写app/package/video.mp4会导致实际寻址为不存在的storage/app/app/package/video.mp4 - 缺少Range请求支持:HTML5视频播放器默认发起分片加载的Range请求,未处理该请求头会导致视频无法加载、进度条不可拖动
具体实现步骤
1. 新增专用路由
在routes/web.php中添加独立的视频流路由:
use App\Http\Controllers\PackageController; Route::get('/packages/{package}/video', [PackageController::class, 'streamVideo'])->name('packages.streamVideo');
2. 编写控制器处理逻辑
在app/Http/Controllers/PackageController.php中实现流输出逻辑,Laravel内置方法可自动兼容Range请求:
public function streamVideo(\App\Models\Package $package) { // 正确的文件路径,local盘根目录为storage/app $path = storage_path('app/package/video.mp4'); // 校验文件存在 if (!file_exists($path)) { abort(404); } return response()->file($path, [ 'Content-Type' => 'video/mp4', 'Accept-Ranges' => 'bytes', ]); // 若要使用自定义VideoStream类,写法如下: // $stream = new \App\Helpers\VideoStream($path); // return $stream->start(); }
3. 修改模型访问器
模型访问器只需要返回路由地址即可:
public function getVideoAttribute() { return route('packages.streamVideo', $this); }
4. 视图层保持原有写法即可
<video controls> <source src="{{ $package->video }}" type="video/mp4"> </video>
额外校验项
- 确认
storage/app/package目录及内部视频文件的权限,保证web服务器运行用户(如www-data、nginx)有可读权限 - 如果你使用路由分组、权限中间件,确保视频路由没有被权限拦截
- 测试时确认视频文件本身是正常可播放的MP4格式,不存在编码错误
内容的提问来源于stack exchange,提问作者kodfire
相关产品推荐
相关产品推荐

