Vue3使用mpegts.js播放FLV视频的配置和遇到的坑解决办法
作者:你开心的样子我好喜欢
这篇文章主要为大家详细介绍了vue3如何使用mpegts.js实现播放flv的直播视频流
1.安装
npm install --save mpegts.js
2.使用(vue组件方法)
<script setup lang="ts"> import {watch} from "vue"; import Mpegts from "mpegts.js"; const props = defineProps<{ url: string, }>() let MPEGTSPlayer: Mpegts.Player; // 播放器实例 watch(props, ()=>{ initPlayer() }) /** * @description 初始化 * */ const initPlayer = async () => { destroyVideo(); const videoElement: HTMLMediaElement = document.getElementById('videoEle') as HTMLMediaElement; if (props.url && videoElement) { Mpegts.isSupported() ? createPlayer(videoElement) : console.log("播放器不可以在您的设备上运行"); } } /** * @description 创建播放器 * @param videoElement 播放器媒体标签 * */ const createPlayer = (videoElement: HTMLMediaElement) => { const mediaDataSource = { type: "flv", isLive: true, cors: true, url: props.url } MPEGTSPlayer = Mpegts.createPlayer(mediaDataSource, { enableWorker: false, enableStashBuffer: false, liveBufferLatencyChasing: true, reuseRedirectedURL: true, lazyLoad: false, deferLoadAfterSourceOpen: false, stashInitialSize: 384, autoCleanupSourceBuffer: true, autoCleanupMinBackwardDuration: 30, autoCleanupMaxBackwardDuration: 60, }) MPEGTSPlayer.attachMediaElement(videoElement); loadPlay(MPEGTSPlayer); } /** * @description 加载视频并且播放 * @param video 需要加载的视频 * */ const loadPlay = (video: any) => { if (video && video['e'] !== null) { // 添加媒体监听 1.监听视频错误 2.监听视频加载 video.on(Mpegts.Events.ERROR, listenerError); video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading); // 加载视频 video.load(); // 播放视频 video.play().then(() => { // 视频播放之后的一些操作 }).catch((error: Error) => { // 视频播放错误的一些操作 }) } } /** * @description 实时监听播放异常 * @param Error 错误信息 * */ const listenerError = (Error: any) => { switch (Error) { case Mpegts.ErrorTypes.NETWORK_ERROR: // 网络异常 break; case Mpegts.ErrorTypes.MEDIA_ERROR: // 媒体错误 break; case Mpegts.ErrorTypes.OTHER_ERROR: // 其他错误 break; } } /** * @description 监听加载事件(直播流可能会导致视频播放暂停,此时会触发此方法) * */ const listenerLoading = () => { } /** * @description 关闭监听、停止播放、断流、销毁 * */ const destroyVideo = () => { if (MPEGTSPlayer && MPEGTSPlayer['e'] != null) { MPEGTSPlayer.off(Mpegts.Events.ERROR, listenerError); MPEGTSPlayer.off(Mpegts.Events.LOADING_COMPLETE, listenerLoading); MPEGTSPlayer.pause(); MPEGTSPlayer.unload(); MPEGTSPlayer.detachMediaElement(); MPEGTSPlayer.destroy(); MPEGTSPlayer = null; } } </script>
3.vue(html部分)
<template> <video autoplay muted controls class="video" id="videoEle" :data-src="videoURL" ></video> </template>
4.样式自定义,此处省略
style:略。
5.可能出现的异常
问题1:[FLVDemuxer] > Unsupported tag type 0, skipped
解决方法:
出现此提示,视频可以正常播放,但会重复出现。可能的问题:流不干净,用FlvBugger或ffmpeg检查下
问题2:[FlvPlayer] > Playback seems stuck at 0,seek to 1.32
解决方法:
出现这个问题,可能是音画不同步出现的提示信息,可以添加一个“追帧”的方法
const end = MPEGTSPlayer.buffered.length > 0 ? MPEGTSPlayer.buffered.end(0) : 0; const differTime = end - MPEGTSPlayer.currentTime; if (differTime >= 2) { MPEGTSPlayer.currentTime = end - .5; }
问题3:Error while initialize transmuxing worker,fallback to inline transmuxing
解决方法:
添加以下配置:
enableWorker:false
提示:此方法还可以解决直播过程导致浏览器奔溃的问题,如果配置的是"enableWorker:true",在直播到一定时长的时候会导致浏览器奔溃。
问题4:The Play() request was interrupted by a call to payse().
play()请求被pause()调用中断
解决方法:
给播放器数据流的地方添加一个定时器,如下:
setTimeout(()=>{ flvPlayer.play() },300)
此方法在一些理想情况下是可以解决的,但是如果因为频繁切换的话还是不能彻底解决该问题,此时需要在播放(参考前面 loadPlay 方法)的时候添加对应的处理
video.play().then(() => { // 正常播放的一些操作 failedMessage.value = ''; // 错误信息用于显示在播放器界面,提示提示用户 }).catch((error: Error) => { // 播放错误的一些处理 console.log('摄像头名称---: ' + cameraName.value + '---', error.message); // 可能出现的播放错误信息:“source” const source = 'Failed to load because no supported source was found.'; if (source == error.message) { failedMessage.value = ' _ 未找到播放源'; } // 可能出现的播放错误信息:“pause” const pause = 'The play() request was interrupted by a call to pause(). https://goo.gl/LdLk22'; if (pause == error.message) { console.log(cameraName.value + ' play() 请求被 pause() 调用中断'); } })
此时会把错误抛出,因为频繁切换,是避免不了 'The Play() request was interrupted by a call to payse(). '。所以只能这样处理。保证切换后的播放不受影响就可以了。
问题5:[MseController] > Failed to execute 'appendBuffer' on 'SourceBuffer':The HTMLMediaElement.error attribute is not null.
解决方法:
一般是发生在切换播放重新拉流之前调用了 destroyVideo 方法,
/** * @description 关闭监听、停止播放、断流、销毁 * */ const destroyVideo = () => { if (MPEGTSPlayer && MPEGTSPlayer['e'] != null) { MPEGTSPlayer.off(Mpegts.Events.ERROR, listenerError); MPEGTSPlayer.off(Mpegts.Events.LOADING_COMPLETE, listenerLoading); MPEGTSPlayer.pause(); MPEGTSPlayer.unload(); MPEGTSPlayer.detachMediaElement(); MPEGTSPlayer.destroy(); MPEGTSPlayer = null; } }
为了所谓的节省内存,没有重新创建播放器,直接调用 以下loadPlay 方法
/** * @description 加载视频并且播放 * @param video 需要加载的视频 * */ const loadPlay = (video: any) => { if (video && video['e'] !== null) { // 添加媒体监听 1.监听视频错误 2.监听视频加载 video.on(Mpegts.Events.ERROR, listenerError); video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading); // 加载视频 video.load(); // 播放视频 video.play().then(() => { // 视频播放之后的一些操作 }).catch((error: Error) => { // 视频播放错误的一些操作 }) } }
所以,只要执行了 destroyVideo 方法,一定要重新 createPlayer 播放器
/** * @description 创建播放器 * @param videoElement 播放器媒体标签 * */ const createPlayer = (videoElement: HTMLMediaElement) => { const mediaDataSource = { type: "flv", isLive: true, cors: true, url: props.url } MPEGTSPlayer = Mpegts.createPlayer(mediaDataSource, { enableWorker: false, enableStashBuffer: false, liveBufferLatencyChasing: true, reuseRedirectedURL: true, lazyLoad: false, deferLoadAfterSourceOpen: false, stashInitialSize: 384, autoCleanupSourceBuffer: true, autoCleanupMinBackwardDuration: 30, autoCleanupMaxBackwardDuration: 60, }) MPEGTSPlayer.attachMediaElement(videoElement); loadPlay(MPEGTSPlayer); }
问题6:Failed to read the 'buffered' property from 'SourceBuffer':This SourceBuffer has been removed from the parent media source.
解决方法:
在打开新页面和切换播放的时候前面的视频已经加载过一次,切换的时候视频资源会二次加载,在每次切换播放新的视频流之前调用 destroyVideo() 方法,销毁前面播放过的视频,
问题7:直播流播放时长到一定长度(一般20分钟以上),监控画面可能会卡住。
解决方法:
此时是因为播放器视频加载结束了,具体问题还有待验证,但是有解决方法,就是在创建播放器播放的时候,添加一个监听 video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading);
/** * @description 实时监听加载播放事件 * 1. 在窗口激活情况下播放结束 且没有网络错误 重新initPlayer * */ const listenerLoading = () => { initPlayer(); }
浏览器控制台出现'The input MediaDataSource has been completely buffered to end'提示,就会触发这个方法,然后在该方法里面调用'initPlayer()',重新创建播放器播放就可以解决了。
以上就是我在项目里面遇到的坑,如果还有没有提到的问题,也可以提出来一起学习参考解决。
问题8:[MSEController] > MediaSource onSourceEnded(和问题7类似)
onSourceBuffer 结束后视频卡住,但流式传输仍在进行。
解决方法:
在下面的方法里里面重新调用 initPlayer()方法,也可以调用createPlayer ()方法重新创建播放器,具体看你的业务
/** * @description 实时监听加载播放事件 * 1. onSourceBuffer 结束后视频卡住,但流式传输仍在进行。 * */ const listenerLoading = () => { initPlayer(); // or createPlayer(); }
注:时间有限,暂时先写这么多。
总结
到此这篇关于Vue3使用mpegts.js播放FLV视频的配置和遇到的坑的文章就介绍到这了,更多相关Vue3 mpegts.js播放FLV视频内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!