Vue3使用mpegts.js播放FLV視頻的配置和遇到的坑解決辦法
這篇文章主要為大家詳細(xì)介紹了vue3如何使用mpegts.js實(shí)現(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; // 播放器實(shí)例
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è)備上運(yùn)行");
}
}
/**
* @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)聽(tīng) 1.監(jiān)聽(tīng)視頻錯(cuò)誤 2.監(jiān)聽(tīng)視頻加載
video.on(Mpegts.Events.ERROR, listenerError);
video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading);
// 加載視頻
video.load();
// 播放視頻
video.play().then(() => {
// 視頻播放之后的一些操作
}).catch((error: Error) => {
// 視頻播放錯(cuò)誤的一些操作
})
}
}
/**
* @description 實(shí)時(shí)監(jiān)聽(tīng)播放異常
* @param Error 錯(cuò)誤信息
* */
const listenerError = (Error: any) => {
switch (Error) {
case Mpegts.ErrorTypes.NETWORK_ERROR:
// 網(wǎng)絡(luò)異常
break;
case Mpegts.ErrorTypes.MEDIA_ERROR:
// 媒體錯(cuò)誤
break;
case Mpegts.ErrorTypes.OTHER_ERROR:
// 其他錯(cuò)誤
break;
}
}
/**
* @description 監(jiān)聽(tīng)加載事件(直播流可能會(huì)導(dǎo)致視頻播放暫停,此時(shí)會(huì)觸發(fā)此方法)
* */
const listenerLoading = () => {
}
/**
* @description 關(guān)閉監(jiān)聽(tīng)、停止播放、斷流、銷毀
* */
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)的異常
問(wèn)題1:[FLVDemuxer] > Unsupported tag type 0, skipped
解決方法:
出現(xiàn)此提示,視頻可以正常播放,但會(huì)重復(fù)出現(xiàn)??赡艿膯?wèn)題:流不干凈,用FlvBugger或ffmpeg檢查下
問(wèn)題2:[FlvPlayer] > Playback seems stuck at 0,seek to 1.32
解決方法:
出現(xiàn)這個(gè)問(wèn)題,可能是音畫不同步出現(xiàn)的提示信息,可以添加一個(gè)“追幀”的方法
const end = MPEGTSPlayer.buffered.length > 0 ? MPEGTSPlayer.buffered.end(0) : 0;
const differTime = end - MPEGTSPlayer.currentTime;
if (differTime >= 2) {
MPEGTSPlayer.currentTime = end - .5;
}問(wèn)題3:Error while initialize transmuxing worker,fallback to inline transmuxing
解決方法:
添加以下配置:
enableWorker:false
提示:此方法還可以解決直播過(guò)程導(dǎo)致瀏覽器奔潰的問(wèn)題,如果配置的是"enableWorker:true",在直播到一定時(shí)長(zhǎng)的時(shí)候會(huì)導(dǎo)致瀏覽器奔潰。
問(wèn)題4:The Play() request was interrupted by a call to payse().
play()請(qǐng)求被pause()調(diào)用中斷
解決方法:
給播放器數(shù)據(jù)流的地方添加一個(gè)定時(shí)器,如下:
setTimeout(()=>{
flvPlayer.play()
},300)此方法在一些理想情況下是可以解決的,但是如果因?yàn)轭l繁切換的話還是不能徹底解決該問(wèn)題,此時(shí)需要在播放(參考前面 loadPlay 方法)的時(shí)候添加對(duì)應(yīng)的處理
video.play().then(() => {
// 正常播放的一些操作
failedMessage.value = ''; // 錯(cuò)誤信息用于顯示在播放器界面,提示提示用戶
}).catch((error: Error) => {
// 播放錯(cuò)誤的一些處理
console.log('攝像頭名稱---: ' + cameraName.value + '---', error.message);
// 可能出現(xiàn)的播放錯(cuò)誤信息:“source”
const source = 'Failed to load because no supported source was found.';
if (source == error.message) {
failedMessage.value = ' _ 未找到播放源';
}
// 可能出現(xiàn)的播放錯(cuò)誤信息:“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() 請(qǐng)求被 pause() 調(diào)用中斷');
}
})此時(shí)會(huì)把錯(cuò)誤拋出,因?yàn)轭l繁切換,是避免不了 'The Play() request was interrupted by a call to payse(). '。所以只能這樣處理。保證切換后的播放不受影響就可以了。
問(wèn)題5:[MseController] > Failed to execute 'appendBuffer' on 'SourceBuffer':The HTMLMediaElement.error attribute is not null.
解決方法:
一般是發(fā)生在切換播放重新拉流之前調(diào)用了 destroyVideo 方法,
/**
* @description 關(guān)閉監(jiān)聽(tīng)、停止播放、斷流、銷毀
* */
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)存,沒(méi)有重新創(chuàng)建播放器,直接調(diào)用 以下loadPlay 方法
/**
* @description 加載視頻并且播放
* @param video 需要加載的視頻
* */
const loadPlay = (video: any) => {
if (video && video['e'] !== null) {
// 添加媒體監(jiān)聽(tīng) 1.監(jiān)聽(tīng)視頻錯(cuò)誤 2.監(jiān)聽(tīng)視頻加載
video.on(Mpegts.Events.ERROR, listenerError);
video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading);
// 加載視頻
video.load();
// 播放視頻
video.play().then(() => {
// 視頻播放之后的一些操作
}).catch((error: Error) => {
// 視頻播放錯(cuò)誤的一些操作
})
}
}所以,只要執(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);
}問(wèn)題6:Failed to read the 'buffered' property from 'SourceBuffer':This SourceBuffer has been removed from the parent media source.
解決方法:
在打開新頁(yè)面和切換播放的時(shí)候前面的視頻已經(jīng)加載過(guò)一次,切換的時(shí)候視頻資源會(huì)二次加載,在每次切換播放新的視頻流之前調(diào)用 destroyVideo() 方法,銷毀前面播放過(guò)的視頻,
問(wèn)題7:直播流播放時(shí)長(zhǎng)到一定長(zhǎng)度(一般20分鐘以上),監(jiān)控畫面可能會(huì)卡住。
解決方法:
此時(shí)是因?yàn)椴シ牌饕曨l加載結(jié)束了,具體問(wèn)題還有待驗(yàn)證,但是有解決方法,就是在創(chuàng)建播放器播放的時(shí)候,添加一個(gè)監(jiān)聽(tīng) video.on(Mpegts.Events.LOADING_COMPLETE, listenerLoading);
/**
* @description 實(shí)時(shí)監(jiān)聽(tīng)加載播放事件
* 1. 在窗口激活情況下播放結(jié)束 且沒(méi)有網(wǎng)絡(luò)錯(cuò)誤 重新initPlayer
* */
const listenerLoading = () => {
initPlayer();
}瀏覽器控制臺(tái)出現(xiàn)'The input MediaDataSource has been completely buffered to end'提示,就會(huì)觸發(fā)這個(gè)方法,然后在該方法里面調(diào)用'initPlayer()',重新創(chuàng)建播放器播放就可以解決了。
以上就是我在項(xiàng)目里面遇到的坑,如果還有沒(méi)有提到的問(wèn)題,也可以提出來(lái)一起學(xué)習(xí)參考解決。
問(wèn)題8:[MSEController] > MediaSource onSourceEnded(和問(wèn)題7類似)
onSourceBuffer 結(jié)束后視頻卡住,但流式傳輸仍在進(jìn)行。
解決方法:
在下面的方法里里面重新調(diào)用 initPlayer()方法,也可以調(diào)用createPlayer ()方法重新創(chuàng)建播放器,具體看你的業(yè)務(wù)
/**
* @description 實(shí)時(shí)監(jiān)聽(tīng)加載播放事件
* 1. onSourceBuffer 結(jié)束后視頻卡住,但流式傳輸仍在進(jìn)行。
* */
const listenerLoading = () => {
initPlayer();
// or
createPlayer();
}注:時(shí)間有限,暫時(shí)先寫這么多。
總結(jié)
到此這篇關(guān)于Vue3使用mpegts.js播放FLV視頻的配置和遇到的坑的文章就介紹到這了,更多相關(guān)Vue3 mpegts.js播放FLV視頻內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中使用this.$set()如何新增數(shù)據(jù),更新視圖
這篇文章主要介紹了Vue中使用this.$set()實(shí)現(xiàn)新增數(shù)據(jù),更新視圖方式。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Vue?quill-editor?編輯器使用及自定義toobar示例詳解
這篇文章主要介紹了Vue quill-editor編輯器使用及自定義toobar示例詳解,這里講解編輯器quil-editor的知識(shí)結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
vue.js 實(shí)現(xiàn)圖片本地預(yù)覽 裁剪 壓縮 上傳功能
這篇文章主要介紹了vue.js 實(shí)現(xiàn)圖片本地預(yù)覽裁剪壓縮上傳功能,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-03-03
Vue分別運(yùn)用class綁定和style綁定通過(guò)點(diǎn)擊實(shí)現(xiàn)樣式切換
這篇文章主要為大家介紹了Vue分別運(yùn)用class綁定和style綁定通過(guò)點(diǎn)擊實(shí)現(xiàn)樣式切換,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
vue3原始值響應(yīng)方案及響應(yīng)丟失問(wèn)題解讀
這篇文章主要介紹了vue3原始值響應(yīng)方案及響應(yīng)丟失問(wèn)題解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Vue實(shí)現(xiàn)購(gòu)物車實(shí)例代碼兩則
這篇文章主要介紹了Vue實(shí)現(xiàn)購(gòu)物車實(shí)例代碼,需要的朋友可以參考下2020-05-05
Vue使用antd組件a-form-model實(shí)現(xiàn)數(shù)據(jù)連續(xù)添加功能
這篇文章主要介紹了Vue使用antd組件a-form-model實(shí)現(xiàn)數(shù)據(jù)連續(xù)添加功能,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Vue-router 切換組件頁(yè)面時(shí)進(jìn)入進(jìn)出動(dòng)畫方法
今天小編就為大家分享一篇Vue-router 切換組件頁(yè)面時(shí)進(jìn)入進(jìn)出動(dòng)畫方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09

