vue使用mpegts.js實(shí)現(xiàn)播放flv的直播視頻流
第一步:引入mpegts.js
npm install --save mpegts.js
第二步:在vue文件中引入mpegts.js的依賴

第三步:編寫展示視頻的盒子
我這里是使用循環(huán)遍歷的方式創(chuàng)建video標(biāo)簽,這樣方便后面隨機(jī)展示視頻使用
<template>
<div>
<el-row>
<el-col :span="24">
<div class="play-video-box">
<input id="tag" v-model="tag" />
<el-button @click="load">重新加載</el-button>
<el-button @click="start">開(kāi)始播放</el-button>
<el-button @click="pause">暫停</el-button>
<el-button @click="destory">全部銷毀</el-button>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="12" v-for="item in 4" :key="item">
<div class="grid-content">
<video
class="video"
:id="getDivClassName(item)"
autoplay="true"
muted="false"
controls="false"
@click="saveMap(item)">
{{ item }}
</video>
</div>
</el-col>
</el-row>
</div>
</template>
第四步:編寫播放視頻和銷毀視頻的方式
<script setup lang="ts">
import mpegts from 'mpegts.js';
import { ref, onUnmounted } from 'vue';
const flvPlayer: any = ref();
const tag = ref(null);
const videoMap = new Map();
/**
* 創(chuàng)建 mpegts 實(shí)例
*/
const initFlv = (ops: { URL: string; elementId: string }) => {
if (tag.value != null && mpegts.isSupported()) {
// 根據(jù)id名稱創(chuàng)建對(duì)應(yīng)的video
const ele = document.getElementById(ops.elementId);
flvPlayer.value = mpegts.createPlayer(
{
type: 'flv', // 指定媒體類型
isLive: true, // 開(kāi)啟直播(是否為實(shí)時(shí)流)
hasAudio: false, // 關(guān)閉聲音(如果拉過(guò)來(lái)的視頻流中沒(méi)有音頻一定要把這里設(shè)置為fasle,否則無(wú)法播放)
cors: true, // 開(kāi)啟跨域訪問(wèn)
url: ops.URL // 指定流鏈接(這里是傳遞過(guò)過(guò)來(lái)的視頻流的地址)
},
{
enableWorker: false, //啟用分離的線程進(jìn)行轉(zhuǎn)換(如果不想看到控制臺(tái)頻繁報(bào)錯(cuò)把它設(shè)置為false,官方的回答是這個(gè)屬性還不穩(wěn)定,所以要測(cè)試實(shí)時(shí)視頻流的話設(shè)置為true控制臺(tái)經(jīng)常報(bào)錯(cuò))
enableStashBuffer: false, //關(guān)閉IO隱藏緩沖區(qū)(如果需要最小延遲,則設(shè)置為false,此項(xiàng)設(shè)置針對(duì)直播視頻流)
stashInitialSize: 128, //減少首幀等待時(shí)長(zhǎng)(針對(duì)實(shí)時(shí)視頻流)
lazyLoad: false, //關(guān)閉懶加載模式(針對(duì)實(shí)時(shí)視頻流)
lazyLoadMaxDuration: 0.2, //懶加載的最大時(shí)長(zhǎng)。單位:秒。建議針對(duì)直播:調(diào)整為200毫秒
deferLoadAfterSourceOpen: false, //在MediaSource sourceopen事件觸發(fā)后加載。在Chrome上,在后臺(tái)打開(kāi)的標(biāo)簽頁(yè)可能不會(huì)觸發(fā)sourceopen事件,除非切換到該標(biāo)簽頁(yè)。
liveBufferLatencyChasing: true, //追蹤內(nèi)部緩沖區(qū)導(dǎo)致的實(shí)時(shí)流延遲
liveBufferLatencyMaxLatency: 1.5, //HTMLMediaElement 中可接受的最大緩沖區(qū)延遲(以秒為單位)之前使用flv.js發(fā)現(xiàn)延時(shí)嚴(yán)重,還有延時(shí)累加的問(wèn)題,而mpegts.js對(duì)此做了優(yōu)化,不需要我們自己設(shè)置快進(jìn)追幀了
liveBufferLatencyMinRemain: 0.3 //HTMLMediaElement 中可接受的最小緩沖區(qū)延遲(以秒為單位)
}
);
// mpegts
flvPlayer.value.attachMediaElement(ele);
videoMap.set(ops.elementId, flvPlayer.value);
play(flvPlayer.value);
flvEvent();
}
};
const play = (flv: any) => {
flv.load();
flv.play();
};
// mpegts
const flvEvent = () => {
// 視頻錯(cuò)誤信息回調(diào)
flvPlayer.value.on(mpegts.Events.ERROR, (errorType: any, errorDetail: any, errorInfo: any) => {
console.log(
'類型:' + JSON.stringify(errorType),
'報(bào)錯(cuò)內(nèi)容' + errorDetail,
'報(bào)錯(cuò)信息' + errorInfo
);
});
//【重要事件監(jiān)聽(tīng)】http 請(qǐng)求建立好后,該事件會(huì)一直監(jiān)聽(tīng) mpegts 實(shí)例
flvPlayer.value.on(mpegts.Events.STATISTICS_INFO, () => {
const end = flvPlayer.value.buffered.end(0); //獲取當(dāng)前buffered值(緩沖區(qū)末尾)
const differTime = end - flvPlayer.value.currentTime; //獲取bufferend與當(dāng)前播放位置的差值
console.log('差值為:' + differTime);
});
};
/**
* 重新加載視頻
*/
const load = () => {
for (let index = 1; index < 5; index++) {
if (!videoMap.has('video-contianer-' + index)) {
initFlv({
URL: 'http://localhost:1010/video/' + tag.value,//這里改成自己要拉流的視頻地址,我這里放的是自己后端推送的1078視頻的flv實(shí)時(shí)視頻流
elementId: 'video-contianer-' + index
});
break;
}
}
};
/**
* 播放
*/
const start = () => flvPlayer.value.play();
/**
* 暫停
*/
const pause = () => flvPlayer.value.pause();
/**
* 銷毀
*/
const destory = () => {
if (videoMap.size > 0) {
for (let [key, flv] of videoMap) {
flv.pause;
flv.unload();
flv.detachMediaElement();
flv.destroy();
flv = null;
videoMap.delete(key);
console.log('銷毀掉視頻:' + key);
}
} else {
console.log('沒(méi)有要銷毀的視頻');
}
};
const getDivClassName = (index: any) => {
return 'video-contianer-' + index;
};
const saveMap = (index: any) => {
test001.value = '-' + index;
videoMap.set(index, test001.value);
};
onUnmounted(() => {
destory();
});
</script>
第五步:設(shè)置展示樣式
<style scoped lang="less">
.play-video-box {
height: 45px;
margin-top: 10px;
margin-left: 200px;
}
.grid-content {
height: 315.5px;
margin-top: 5px;
margin-left: 5px;
}
#tag {
width: 280px;
height: 30px;
}
//所有控件
video::-webkit-media-controls-enclosure {
display: none;
}
.video {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
第六步:效果圖
(我的是在輸入框中輸入想要拉取的設(shè)備和通道號(hào)點(diǎn)擊重新加載即可,多次點(diǎn)擊會(huì)將四個(gè)窗格都展示同樣的視頻)

以上就是vue使用mpegts.js實(shí)現(xiàn)播放flv的直播視頻流的詳細(xì)內(nèi)容,更多關(guān)于vue播放flv的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
elementUI table表格動(dòng)態(tài)合并的示例代碼
這篇文章主要介紹了elementUI table表格動(dòng)態(tài)合并的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Vue3使用Proxy實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽(tīng)的原因分析
在本篇文章里小編給大家整理的是一篇關(guān)于Vue3使用Proxy實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽(tīng)的原因分析內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)參考下。2021-11-11
vue使用wavesurfer.js解決音頻可視化播放問(wèn)題
Wavesurfer.js是一款基于HTML5?canvas和Web?Audio的聲紋可視化插件,功能十分強(qiáng)大,在Vue框架中嵌入使用該插件,今天重點(diǎn)給大家介紹下vue使用wavesurfer.js解決音頻可視化播放問(wèn)題,感興趣的朋友一起看看吧2022-04-04
vue 項(xiàng)目全屏插件screenfull使用案例
這篇文章主要介紹了vue 項(xiàng)目全屏插件screenfull使用案例,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12
改變vue請(qǐng)求過(guò)來(lái)的數(shù)據(jù)中的某一項(xiàng)值的方法(詳解)
下面小編就為大家分享一篇改變vue請(qǐng)求過(guò)來(lái)的數(shù)據(jù)中的某一項(xiàng)值的方法(詳解),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
淺談在vue中使用mint-ui swipe遇到的問(wèn)題
今天小編就為大家分享一篇淺談在vue中使用mint-ui swipe遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
vue.js整合vux中的上拉加載下拉刷新實(shí)例教程
這篇文章主要給大家介紹了關(guān)于vue.js整合vux中上拉加載下拉刷新的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01

