在Laravel中如何流式播放HLS、m3u8格式的视频?
m3u8格式视频播放与下载实现方案
播放功能修复与优化
你现有代码的核心问题是加载m3u8资源时写死了固定路径,没有调用实际存储的视频路径,优化后的前端代码实现点击按钮才触发播放,避免页面加载时占用多余带宽:
@if( $item->media_type=='v') <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <button id="play_{{ $item->id }}" style="margin-right: 10px;">播放视频</button> <button id="download_{{ $item->id }}">下载视频</button> <video id="video_{{ $item->id }}" controls width="200px" height="200px" style="display: none; margin-top: 10px;"></video> <script> // 播放逻辑 document.getElementById('play_{{ $item->id }}').addEventListener('click', function () { const video = document.getElementById('video_{{ $item->id }}') const realUrl = 'https://cdn.kenan.net/{{ $item->media_path }}' video.style.display = 'block' if (Hls.isSupported()) { const hls = new Hls() hls.loadSource(realUrl) hls.attachMedia(video) hls.on(Hls.Events.MANIFEST_PARSED, function () { video.play() }) } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = realUrl video.addEventListener('canplay', function () { video.play() }) } }) // 下载触发逻辑 document.getElementById('download_{{ $item->id }}').addEventListener('click', function () { window.location.href = '/video/download?path={{ urlencode($item->media_path) }}' }) </script> @endif
后端下载功能实现
m3u8是分片视频索引文件,前端无法直接下载为可播放的视频文件,需要通过laravel-ffmpeg在后端将m3u8转码为MP4后再提供下载,参考代码如下:
控制器代码
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg; use Illuminate\Support\Facades\Storage; class VideoController extends Controller { public function download(Request $request) { $mediaPath = $request->input('path'); $fullM3u8Url = 'https://cdn.kenan.net/' . $mediaPath; $saveName = pathinfo($mediaPath, PATHINFO_FILENAME) . '.mp4'; $tempSavePath = 'tmp/' . $saveName; // 转码为MP4保存到临时目录 FFMpeg::openUrl($fullM3u8Url) ->export() ->toDisk('public') ->inFormat(new \FFMpeg\Format\Video\X264('aac')) ->save($tempSavePath); // 返回下载响应,下载完成后自动删除临时文件 return response() ->download(Storage::disk('public')->path($tempSavePath), $saveName) ->deleteFileAfterSend(true); } }
路由配置
在routes/web.php中添加下载路由:
Route::get('/video/download', [\App\Http\Controllers\VideoController::class, 'download']);
注意事项
- 确保你的服务器已经正确安装FFmpeg环境,否则laravel-ffmpeg无法正常执行转码操作
- 大体积视频转码耗时较长,建议配合队列异步处理,避免HTTP请求超时
- 可根据业务需要添加权限校验逻辑,避免视频资源被未授权用户下载
内容的提问来源于stack exchange,提问作者black man
相关产品推荐
相关产品推荐

