flv.js在vue中的使用方法
Flv.js 是 HTML5 Flash 視頻(FLV)播放器,純原生 JavaScript 開發(fā),沒有用到 Flash。由 bilibili 網(wǎng)站開源。它的工作原理是將 FLV 文件流轉(zhuǎn)碼復(fù)用成 ISO BMFF(MP4 碎片)片段,然后通過 Media Source Extensions 將 MP4 片段喂進(jìn)瀏覽器。
使用方法
<template>
<div class="video" :style="{ height: voidHeight }">
<video ref="videoElement" muted controls autoplay controlslist="nodownload noplaybackrate noremoteplayback" disablePictureInPicture="true" v-if="!imgError"></video>
<div class="img_error" v-if="imgError">
<p>無法連接相關(guān)設(shè)備</p>
</div>
</div>
</template>
<script>
import flvjs from "flv.js";
export default {
name: "assemblyFlv",
props: ["url", "height", "destroy","playon"], // 視頻流路徑,播放器高度,是否銷毀播放器
data() {
return {
flvPlayer: "",
imgError: false,
voidHeight: "",
playOn:true
};
},
mounted() {
// 判斷是否傳入高度,如果沒有,高度100%
this.height ? (this.voidHeight = this.height) : (this.voidHeight = "100%");
// 頁面加載完成后,初始化
this.$nextTick(() => {
this.init(this.url);
});
},
methods: {
// 初始化
init(source) {
if (flvjs.isSupported()) {
this.flvPlayer = flvjs.createPlayer(
{
type: "flv",
url: source,
isLive: true,
},
{
enableWorker: false, //不啟用分離線程
enableStashBuffer: false, //關(guān)閉IO隱藏緩沖區(qū)
reuseRedirectedURL: true, //重用301/302重定向url,用于隨后的請求,如查找、重新連接等。
autoCleanupSourceBuffer: true, //自動清除緩存
}
);
var videoElement = this.$refs.videoElement;
this.flvPlayer.attachMediaElement(this.$refs.videoElement);
if (this.url !== "" && this.url !== null) {
this.flvPlayer.load();
//this.flvPlayer.play();
setTimeout(() => { this.flvPlayer.play(); }, 100);
// 加載完成
this.flvPlayer.on(flvjs.Events.LOADING_COMPLETE, () => {
this.imgError = false;
});
// 加載失敗
this.flvPlayer.on(
flvjs.Events.ERROR,
() => {
if (this.flvPlayer) {
this.reloadVideo(this.flvPlayer);
}else{
this.imgError = true;
}
},
(error) => {
console.log(error);
}
);
this.flvPlayer.on(flvjs.Events.STATISTICS_INFO, (res) =>{
if(this.playon != false){
if (this.lastDecodedFrame == 0) {
this.lastDecodedFrame = res.decodedFrames;
console.log(this.lastDecodedFrame)
return;
}
if (this.lastDecodedFrame != res.decodedFrames) {
this.lastDecodedFrame = res.decodedFrames;
} else {
this.lastDecodedFrame = 0;
console.log('卡住重連')
if (this.flvPlayer) {
this.reloadVideo(this.flvPlayer);
console.log('卡住重連完成')
}
}
}
});
videoElement.addEventListener("progress", () => {
if(videoElement.buffered.length != 0){
let end = videoElement.buffered.end(0); //獲取當(dāng)前buffered值(緩沖區(qū)末尾)
let delta = end - videoElement.currentTime; //獲取buffered與當(dāng)前播放位置的差值
// 延遲過大,通過跳幀的方式更新視頻
if (delta > 10 || delta < 0) {
this.flvPlayer.currentTime = this.flvPlayer.buffered.end(0) - 1;
console.log('跳幀')
return;
}
// 追幀
if (delta > 1) {
videoElement.playbackRate = 1.1;
console.log('追幀')
} else {
videoElement.playbackRate = 1;
console.log('正常')
}
}
});
// 點(diǎn)擊播放按鈕后,更新視頻
videoElement.addEventListener("play", () => {
if(videoElement.buffered.length > 0){
let end = videoElement.buffered.end(0) - 1;
this.flvPlayer.currentTime = end;
console.log('播放最新')
}
});
// 網(wǎng)頁重新激活后,更新視頻
window.onfocus = () => {
if(videoElement.buffered.length > 0){
let end1 = videoElement.buffered.end(0) - 1;
this.flvPlayer.currentTime = end1;
console.log('頁面切換')
}
};
}
} else {
this.imgError = true;
}
},
//斷線重連
reloadVideo(flvPlayer) {
this.detachMediaElement();
this.init(this.url);
console.log('斷線重連')
},
// 銷毀
detachMediaElement() {
this.flvPlayer.pause();
this.flvPlayer.unload();
this.flvPlayer.detachMediaElement();
this.flvPlayer.destroy();
this.flvPlayer = "";
},
},
watch: {
url() {
this.imgError = false;
// 切換流之前,判斷之前的流是否銷毀
this.flvPlayer == "" ? "" : this.detachMediaElement();
// 初始化
this.init(this.url);
},
destroy() {
// 傳入開關(guān)值
if (this.destroy) {
this.init(this.url);
} else {
this.flvPlayer == "" ? "" : this.detachMediaElement();
}
},
playon() {
this.reloadVideo(this.flvPlayer);
}
},
beforeDestroy() {
this.detachMediaElement();
},
};
</script>
<style scoped>
.video {
position: relative;
height: 100%;
}
.video video {
width: 100%;
height: 100%;
object-fit: fill;
}
.video video::-webkit-media-controls-play-button{
display: none;
}
.video video::-webkit-media-controls-toggle-closed-captions-button {
display: none;
}
.video video::-webkit-media-controls-timeline {
display: none;
}
.video video::-webkit-media-controls-current-time-display {
display: none;
}
.video video::-webkit-media-controls-time-remaining-display {
display: none;
}
.img_error {
position: absolute;
top: 30%;
left: 50%;
margin-left: -120px;
text-align: center;
}
.img_error > img {
margin-bottom: 1em;
}
.img_error > p {
color: #00fdff;
font-weight: bold;
font-size: 1.2em;
}
</style>封裝:
子組件封裝:
<template>
<div class="video-container">
<video ref="videoElement" class="centeredVideo" controls autoplay muted></video>
</div>
</template>
<script>
import flvjs from "flv.js"; //引入flv
export default {
props: {
url : String,
},
data() {
return {
// src: ["http://172.21.1.111/live?port=1935&app=myapp&stream=streamname"],
};
},
mounted() {
this.flv_load(this.url);
},
methods: {
flv_load(url) {
if (flvjs.isSupported()) {
let videoElement = this.$refs.videoElement;
this.flvPlayer = flvjs.createPlayer(
{
type: "flv", //媒體類型
url: url, //flv格式媒體URL
isLive: true, //數(shù)據(jù)源是否為直播流
hasAudio: false, //數(shù)據(jù)源是否包含有音頻
hasVideo: true, //數(shù)據(jù)源是否包含有視頻
enableStashBuffer: false, //是否啟用緩存區(qū)
},
{
enableWorker: false, // 是否啟用分離的線程進(jìn)行轉(zhuǎn)換
enableStashBuffer: false, //關(guān)閉IO隱藏緩沖區(qū)
autoCleanupSourceBuffer: true, //自動清除緩存
}
);
this.flvPlayer.attachMediaElement(videoElement); //將播放實(shí)例注冊到節(jié)點(diǎn)
this.flvPlayer.load(); //加載數(shù)據(jù)流
this.flvPlayer.play(); //播放數(shù)據(jù)流
}
},
},
};
</script>
<style scoped>
/* .video-container {
display: inline-block;
margin-right: 10px;
width: 32%;
height: 45%;
} */
.centeredVideo {
width: 100%;
}
</style>父組件調(diào)用:
<template>
<el-card class="box-card">
<div class="flvbox" v-for="(item,index) in src" :key="index">
<!-- <VideoFlv url="http://172.21.1.111/live?port=1935&app=myapp&stream=streamname" /> -->
<VideoFlv :url="item" />
</div>
</el-card>
</template>
<script>
import VideoFlv from "./VideoFlv.vue";
export default {
components:{
VideoFlv
},
data() {
return {
src: [
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
"http://172.21.1.111/live?port=1935&app=myapp&stream=streamname",
"https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv",
],
};
},
};
</script>
<style scoped>
.flvbox {
display: inline-block;
margin-right: 10px;
width: 32%;
}
</style>因?yàn)橐曨l需要實(shí)時的 后邊發(fā)現(xiàn)上邊寫法暫停之后和切換頁面之后 會有延遲 所以開發(fā)讓新加個刷新按鈕 也已滿足 然后這個api的寫法我嘗試很多 追幀啊 更新視頻啊 都沒生效 父組件重新傳值 因?yàn)橹禌]有變化 所以也沒有重新渲染 所以用到了key 屬性 vue每次渲染的時候會去拿這個key 值做對比,如果這一次的key 值和上一次的key值是不一樣的才會重新渲染dom 元素,否則保持上一次的元素狀態(tài)。所以我用了一個時間戳方法



flv.js常用方法
1:flvjs.isSupported():判斷當(dāng)前瀏覽器是否支持播放
2:flvPlayer = flvjs.createPlayer(mediaDataSource: MediaDataSource, config?: Config):創(chuàng)建一個播放實(shí)例
3:flvPlayer.attachMediaElement(mediaElement: HTMLMediaElement):將播放實(shí)例注冊到video節(jié)點(diǎn)
4:flvPlayer.load():加載數(shù)據(jù)流
5:flvPlayer.play():播放數(shù)據(jù)流
6:flvPlayer.pause():暫停播放數(shù)據(jù)流
7:flvPlayer.unload():取消數(shù)據(jù)流加載
8:flvPlayer.detachMediaElement():將播放實(shí)例從節(jié)點(diǎn)中取出
9:flvPlayer.destroy():銷毀播放實(shí)例
到此這篇關(guān)于flv.js在vue中的使用的文章就介紹到這了,更多相關(guān)vue使用flv.js內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用vuex實(shí)現(xiàn)首頁導(dǎo)航切換不同路由的方法
這篇文章主要介紹了vue使用vuex實(shí)現(xiàn)首頁導(dǎo)航切換不同路由的方法 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05
Vue結(jié)合原生js實(shí)現(xiàn)自定義組件自動生成示例
這篇文章主要介紹了Vue結(jié)合原生js實(shí)現(xiàn)自定義組件自動生成示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01
Vue實(shí)現(xiàn)動態(tài)圓環(huán)百分比進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)動態(tài)圓環(huán)百分比進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
詳解如何使用Vue-PDF在應(yīng)用中嵌入PDF文檔
在現(xiàn)代Web應(yīng)用中,PDF文檔的使用非常普遍,因?yàn)樗梢栽诟鞣N設(shè)備和操作系統(tǒng)上保持一致的外觀和格式,本文我們就來探討一下如何在Vue.js應(yīng)用中使用vue-pdf庫嵌入PDF文檔吧2023-08-08

