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('正常') } } }); // 點擊播放按鈕后,更新視頻 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); //將播放實例注冊到節(jié)點 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>
因為視頻需要實時的 后邊發(fā)現(xiàn)上邊寫法暫停之后和切換頁面之后 會有延遲 所以開發(fā)讓新加個刷新按鈕 也已滿足 然后這個api的寫法我嘗試很多 追幀啊 更新視頻啊 都沒生效 父組件重新傳值 因為值沒有變化 所以也沒有重新渲染 所以用到了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)建一個播放實例
3:flvPlayer.attachMediaElement(mediaElement: HTMLMediaElement):將播放實例注冊到video節(jié)點
4:flvPlayer.load():加載數(shù)據(jù)流
5:flvPlayer.play():播放數(shù)據(jù)流
6:flvPlayer.pause():暫停播放數(shù)據(jù)流
7:flvPlayer.unload():取消數(shù)據(jù)流加載
8:flvPlayer.detachMediaElement():將播放實例從節(jié)點中取出
9:flvPlayer.destroy():銷毀播放實例
到此這篇關(guān)于flv.js在vue中的使用的文章就介紹到這了,更多相關(guān)vue使用flv.js內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解HTTP4種方法(GET、POST、 PUT和DELETE)
本文介紹了HTTP協(xié)議中的四種方法:GET、POST、PUT和DELETE,分別用于不同的操作,GET用于獲取數(shù)據(jù),POST用于提交數(shù)據(jù),PUT用于創(chuàng)建或更新資源,DELETE用于刪除資源,每種方法都有其特點和適用場景,了解這些方法有助于更好地進(jìn)行數(shù)據(jù)交互和開發(fā),感興趣的朋友一起看看吧2025-02-02前端請求超時截斷axios?timeout設(shè)置未生效情況解決記錄
在項目中遇到了后臺接口返回數(shù)據(jù)慢的時候往往需要設(shè)置請求失效時間,在項目中遇到設(shè)置timeout失效問題由此記錄下來,這篇文章主要給大家介紹了前端請求超時截斷axios?timeout設(shè)置未生效情況解決的相關(guān)資料,需要的朋友可以參考下2024-07-07vue自定義指令實現(xiàn)僅支持輸入數(shù)字和浮點型的示例
今天小編就為大家分享一篇vue自定義指令實現(xiàn)僅支持輸入數(shù)字和浮點型的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10如何使用vuejs實現(xiàn)更好的Form validation?
如何使用vuejs實現(xiàn)更好的Form validation?這篇文章主要介紹了vue-form插件的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04