Vue3使用mpegts.js播放FLV視頻的配置和遇到的坑解決辦法
這篇文章主要為大家詳細(xì)介紹了vue3如何使用mpegts.js實現(xiàn)播放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("播放器不可以在您的設(shè)備上運行"); } } /** * @description 創(chuàng)建播放器 * @param videoElement 播放器媒體標(biāo)簽 * */ 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) { // 添加媒體監(jiān)聽 1.監(jiān)聽視頻錯誤 2.監(jiān)聽視頻加載 video.on(Mpegts.Events.ERROR, listenerError); video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading); // 加載視頻 video.load(); // 播放視頻 video.play().then(() => { // 視頻播放之后的一些操作 }).catch((error: Error) => { // 視頻播放錯誤的一些操作 }) } } /** * @description 實時監(jiān)聽播放異常 * @param Error 錯誤信息 * */ const listenerError = (Error: any) => { switch (Error) { case Mpegts.ErrorTypes.NETWORK_ERROR: // 網(wǎng)絡(luò)異常 break; case Mpegts.ErrorTypes.MEDIA_ERROR: // 媒體錯誤 break; case Mpegts.ErrorTypes.OTHER_ERROR: // 其他錯誤 break; } } /** * @description 監(jiān)聽加載事件(直播流可能會導(dǎo)致視頻播放暫停,此時會觸發(fā)此方法) * */ const listenerLoading = () => { } /** * @description 關(guān)閉監(jiān)聽、停止播放、斷流、銷毀 * */ 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.可能出現(xiàn)的異常
問題1:[FLVDemuxer] > Unsupported tag type 0, skipped
解決方法:
出現(xiàn)此提示,視頻可以正常播放,但會重復(fù)出現(xiàn)??赡艿膯栴}:流不干凈,用FlvBugger或ffmpeg檢查下
問題2:[FlvPlayer] > Playback seems stuck at 0,seek to 1.32
解決方法:
出現(xiàn)這個問題,可能是音畫不同步出現(xiàn)的提示信息,可以添加一個“追幀”的方法
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
提示:此方法還可以解決直播過程導(dǎo)致瀏覽器奔潰的問題,如果配置的是"enableWorker:true",在直播到一定時長的時候會導(dǎo)致瀏覽器奔潰。
問題4:The Play() request was interrupted by a call to payse().
play()請求被pause()調(diào)用中斷
解決方法:
給播放器數(shù)據(jù)流的地方添加一個定時器,如下:
setTimeout(()=>{ flvPlayer.play() },300)
此方法在一些理想情況下是可以解決的,但是如果因為頻繁切換的話還是不能徹底解決該問題,此時需要在播放(參考前面 loadPlay 方法)的時候添加對應(yīng)的處理
video.play().then(() => { // 正常播放的一些操作 failedMessage.value = ''; // 錯誤信息用于顯示在播放器界面,提示提示用戶 }).catch((error: Error) => { // 播放錯誤的一些處理 console.log('攝像頭名稱---: ' + cameraName.value + '---', error.message); // 可能出現(xiàn)的播放錯誤信息:“source” const source = 'Failed to load because no supported source was found.'; if (source == error.message) { failedMessage.value = ' _ 未找到播放源'; } // 可能出現(xiàn)的播放錯誤信息:“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() 調(diào)用中斷'); } })
此時會把錯誤拋出,因為頻繁切換,是避免不了 '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.
解決方法:
一般是發(fā)生在切換播放重新拉流之前調(diào)用了 destroyVideo 方法,
/** * @description 關(guān)閉監(jiān)聽、停止播放、斷流、銷毀 * */ 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; } }
為了所謂的節(jié)省內(nèi)存,沒有重新創(chuàng)建播放器,直接調(diào)用 以下loadPlay 方法
/** * @description 加載視頻并且播放 * @param video 需要加載的視頻 * */ const loadPlay = (video: any) => { if (video && video['e'] !== null) { // 添加媒體監(jiān)聽 1.監(jiān)聽視頻錯誤 2.監(jiān)聽視頻加載 video.on(Mpegts.Events.ERROR, listenerError); video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading); // 加載視頻 video.load(); // 播放視頻 video.play().then(() => { // 視頻播放之后的一些操作 }).catch((error: Error) => { // 視頻播放錯誤的一些操作 }) } }
所以,只要執(zhí)行了 destroyVideo 方法,一定要重新 createPlayer 播放器
/** * @description 創(chuàng)建播放器 * @param videoElement 播放器媒體標(biāo)簽 * */ 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.
解決方法:
在打開新頁面和切換播放的時候前面的視頻已經(jīng)加載過一次,切換的時候視頻資源會二次加載,在每次切換播放新的視頻流之前調(diào)用 destroyVideo() 方法,銷毀前面播放過的視頻,
問題7:直播流播放時長到一定長度(一般20分鐘以上),監(jiān)控畫面可能會卡住。
解決方法:
此時是因為播放器視頻加載結(jié)束了,具體問題還有待驗證,但是有解決方法,就是在創(chuàng)建播放器播放的時候,添加一個監(jiān)聽 video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading);
/** * @description 實時監(jiān)聽加載播放事件 * 1. 在窗口激活情況下播放結(jié)束 且沒有網(wǎng)絡(luò)錯誤 重新initPlayer * */ const listenerLoading = () => { initPlayer(); }
瀏覽器控制臺出現(xiàn)'The input MediaDataSource has been completely buffered to end'提示,就會觸發(fā)這個方法,然后在該方法里面調(diào)用'initPlayer()',重新創(chuàng)建播放器播放就可以解決了。
以上就是我在項目里面遇到的坑,如果還有沒有提到的問題,也可以提出來一起學(xué)習(xí)參考解決。
問題8:[MSEController] > MediaSource onSourceEnded(和問題7類似)
onSourceBuffer 結(jié)束后視頻卡住,但流式傳輸仍在進(jìn)行。
解決方法:
在下面的方法里里面重新調(diào)用 initPlayer()方法,也可以調(diào)用createPlayer ()方法重新創(chuàng)建播放器,具體看你的業(yè)務(wù)
/** * @description 實時監(jiān)聽加載播放事件 * 1. onSourceBuffer 結(jié)束后視頻卡住,但流式傳輸仍在進(jìn)行。 * */ const listenerLoading = () => { initPlayer(); // or createPlayer(); }
注:時間有限,暫時先寫這么多。
總結(jié)
到此這篇關(guān)于Vue3使用mpegts.js播放FLV視頻的配置和遇到的坑的文章就介紹到這了,更多相關(guān)Vue3 mpegts.js播放FLV視頻內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue2中使用自定義指令實現(xiàn)el-table虛擬列表的代碼示例
在實際開發(fā)中,我們可能會面臨其他需求,例如在 el-table 中無法使用分頁技術(shù)的情況下展示海量數(shù)據(jù),這種情況下,頁面可能會出現(xiàn)卡頓,嚴(yán)重時甚至可能引發(fā)瀏覽器崩潰,所以針對這個問題本文給大家介紹了vue2中使用自定義指令實現(xiàn)el-table虛擬列表,需要的朋友可以參考下2025-01-01vue 導(dǎo)航內(nèi)容設(shè)置選中狀態(tài)樣式的例子
今天小編就為大家分享一篇vue 導(dǎo)航內(nèi)容設(shè)置選中狀態(tài)樣式的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue.js 1.x與2.0中js實時監(jiān)聽input值的變化
這篇文章主要介紹了vue.js 1.x與vue.js2.0中js實時監(jiān)聽input值的變化的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03