求助:Laravel网站非MP4格式视频在线播放解决方案
解决方案:在Laravel中在线播放非MP4格式视频
你的核心问题是浏览器HTML5原生播放器仅支持MP4(H.264编码)等少数格式,MTS、AVI这类格式无法直接播放,会触发下载。以下是几种可行的解决思路,按推荐优先级排序:
1. 服务器端批量转码为MP4(最兼容方案)
将所有非MP4格式视频转码为浏览器通用的MP4(H.264 + AAC编码),是最稳妥的方式,无需依赖浏览器或第三方播放器的特殊支持。
实现步骤:
- 安装FFmpeg工具:服务器上先安装FFmpeg(Linux用
apt install ffmpeg,Windows下载官方二进制包),这是视频转码的核心工具。 - 引入Laravel FFmpeg包:使用封装好的Laravel扩展简化操作:
composer require pbmedia/laravel-ffmpeg - 编写转码逻辑:可以在视频上传时自动转码,或后台批量处理已上传视频:
// 假设$video是视频模型实例,$temoignage是关联模型 $originalPath = storage_path('app/public/folder/video/' . $temoignage->title . '/' . $video->name); $outputFilename = pathinfo($video->name, PATHINFO_FILENAME) . '.mp4'; $outputPath = storage_path('app/public/folder/video/' . $temoignage->title . '/' . $outputFilename); // 转码为H.264编码的MP4 FFmpeg::fromDisk('public') ->open($originalPath) ->export() ->toDisk('public') ->inFormat(new \FFMpeg\Format\Video\X264()) ->save($outputPath); // 将转码后的文件名存入数据库,方便前端调用 $video->update(['mp4_filename' => $outputFilename]); - 前端调整:优先加载转码后的MP4文件,原文件作为降级下载选项:
<video id="video-{{ $video->id }}" class="video-js" preload="auto" width="320" height="240" controls data-setup="{}"> @if($video->mp4_filename) <source src="{{ asset('folder/video/'. $temoignage->title . '/' . $video->mp4_filename) }}" type="video/mp4"> @endif <!-- 原文件作为备选 --> <source src="{{ asset('folder/video/'. $temoignage->title . '/' . $video->name) }}" type="{{ $video->mime_type }}"> Votre navigateur ne supporte pas la balise vidéo. <p class="vjs-no-js"> Pour regarder cette vidéo, veuillez activer JavaScript, ou envisagez de mettre à jour votre navigateur à une version qui prend en charge les vidéos HTML5. </p> </video>
2. 实时转码为流媒体格式播放
如果不想提前转码,可以将视频实时转码为HLS流媒体格式,前端用支持的播放器加载。这种方式适合视频数量多、存储空间有限的场景,但对服务器性能要求较高。
实现步骤:
- 创建流媒体路由:在Laravel中新增路由,处理实时转码请求:
Route::get('video/stream/{temoignage}/{video}', function ($temoignageTitle, $videoName) { $path = storage_path('app/public/folder/video/' . $temoignageTitle . '/' . $videoName); // 设置流媒体响应头 header('Content-Type: application/x-mpegURL'); // 用FFmpeg实时转码为HLS并输出 passthru("ffmpeg -i $path -c:v libx264 -c:a aac -f hls -hls_time 10 -hls_list_size 0 -"); exit; })->name('video.stream'); - 前端用HLS.js播放:引入HLS.js库加载流媒体:
<video id="video-{{ $video->id }}" class="video-js" preload="auto" width="320" height="240" controls></video> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <script> document.addEventListener('DOMContentLoaded', function() { const video = document.getElementById('video-{{ $video->id }}'); const streamUrl = "{{ route('video.stream', [$temoignage->title, $video->name]) }}"; if (Hls.isSupported()) { const hls = new Hls(); hls.loadSource(streamUrl); hls.attachMedia(video); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = streamUrl; } }); </script>
3. 修正现有代码的细节问题
你当前代码存在两个影响功能的小问题:
- 重复的video ID:循环中每个视频都用
id="my-video",会导致JavaScript选择器冲突,应改为动态ID:id="video-{{ $video->id }}"。 - 补充MIME类型:给source标签添加
type属性,帮助浏览器识别格式(仅作补充,不保证兼容):
常见格式的MIME类型:MTS为<source src="{{ asset('folder/video/'. $temoignage->title . '/' . $video->name) }}" type="{{ $video->mime_type }}">video/MP2T,AVI为video/x-msvideo。
内容的提问来源于stack exchange,提问作者Yakoub Fergag
相关产品推荐
相关产品推荐

