vue2之jessibuca視頻插件使用教程詳細(xì)講解
jessibuca簡介
Jessibuca是一款開源的純H5直播流播放器,通過Emscripten將音視頻解碼庫編譯成Js(ams.js/wasm)運(yùn)行于瀏覽器之中。兼容幾乎所有瀏覽器,可以運(yùn)行在PC、手機(jī)、微信中,無需額外安裝插件。
前期準(zhǔn)備
下載相關(guān)js
從官網(wǎng)下載相關(guān)壓縮包將文件移入自身項(xiàng)目中,并根據(jù)自身vue版本放入Public或者Static文件夾下。
jessibuca官網(wǎng)-源碼下載鏈接 或者 點(diǎn)擊這里下載
vue index.html文件引入
<script type="text/javascript" src="/jessibuca/jessibuca.js"></script>
組件封裝
<template> <div ref="container" @dblclick="fullscreenSwich" style="width: 100%; height: 100%; background-color: #000000; margin: 0 auto; position: relative" > <div class="buttons-box" id="buttonsBox" > <div class="buttons-box-left"> <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick" ></i> <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause" ></i> <i class="iconfont icon-stop jessibuca-btn" @click="destroy" ></i> <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="mute()" ></i> <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="cancelMute()" ></i> </div> <div class="buttons-box-right"> <span class="jessibuca-btn">{{ kBps }} kb/s</span> <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot" style="font-size: 1rem !important" ></i> <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick" ></i> <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich" ></i> <i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich" ></i> <i style="font-size: 28px" class="iconfont icon-video-close jessibuca-btn" @click="closeVideo()" ></i> </div> </div> </div> </template> <script> let jessibucaPlayer = {}; export default { name: "wkVideoPlayer", data() { return { playing: false, isNotMute: false, quieting: false, fullscreen: false, loaded: false, // mute speed: 0, performance: "", // 工作情況 kBps: 0, btnDom: null, }; }, props: ["videoUrl", "error", "hasAudio", "height"], mounted() { this.$nextTick(() => { this.updatePlayerDomSize(); this.btnDom = document.getElementById("buttonsBox"); window.onresize = () => { this.updatePlayerDomSize(); }; if (this.videoUrl) { this.play(this.videoUrl); } else { return; } }); }, watch: { videoUrl(newData) { this.play(newData); }, immediate: true, }, methods: { updatePlayerDomSize() { let dom = this.$refs.container; let width = dom.parentNode.clientWidth; let height = dom.parentNode.clientHeight; const clientHeight = Math.min( document.body.clientHeight, document.documentElement.clientHeight ); if (height > clientHeight) { height = clientHeight; width = (16 / 9) * height; } dom.style.width = width + "px"; dom.style.height = height + "px"; }, create() { let options = {}; jessibucaPlayer[this._uid] = new window.Jessibuca( Object.assign( { container: this.$refs.container, autoWasm: true, // 在使用MSE或者Webcodecs 播放H265的時(shí)候,是否自動降級到wasm模式。 background: "", //背景圖片 controlAutoHide: false, //底部控制臺是否自動隱藏 debug: false, //是否開啟控制臺調(diào)試打印 decoder: "/jessibuca/decoder.js", hasAudio: typeof this.hasAudio == "undefined" ? true : this.hasAudio, // 是否有音頻,如果設(shè)置false,則不對音頻數(shù)據(jù)解碼,提升性能。 hasVideo: true, // 是否開啟控制臺調(diào)試打印 heartTimeout: 5, //設(shè)置超時(shí)時(shí)長, 單位秒播放中途,如果超過設(shè)定時(shí)長無數(shù)據(jù)返回,則回調(diào)timeout事件 heartTimeoutReplay: true, //是否開啟心跳超時(shí)之后自動再播放 heartTimeoutReplayTimes: 3, //重試次數(shù) heartTimeoutReplay 重試失敗之后,不再重新播放視頻地址。如果想無限次重試,可以設(shè)置為-1 hiddenAutoPause: false, //是否開啟當(dāng)頁面的'visibilityState'變?yōu)?hidden'的時(shí)候,自動暫停播放。 hotKey: false, //是否開啟鍵盤快捷鍵 esc -> 退出全屏;arrowUp -> 聲音增加;arrowDown -> 聲音減少; isFlv: false, //當(dāng)為true的時(shí)候:ws協(xié)議不檢驗(yàn)是否以.flv為依據(jù),進(jìn)行協(xié)議解析。 isFullResize: false, //當(dāng)為true的時(shí)候:視頻畫面做等比縮放后,完全填充canvas區(qū)域,畫面不被拉伸,沒有黑邊,但畫面顯示不全 isNotMute: this.isNotMute, // 是否開啟聲音,默認(rèn)是關(guān)閉聲音播放的。 isResize: false, //當(dāng)為true的時(shí)候:視頻畫面做等比縮放后,高或?qū)拰Rcanvas區(qū)域,畫面不被拉伸,但有黑邊。 當(dāng)為false的時(shí)候:視頻畫面完全填充canvas區(qū)域,畫面會被拉伸。 keepScreenOn: false, //開啟屏幕常亮,在手機(jī)瀏覽器上, canvas標(biāo)簽渲染視頻并不會像video標(biāo)簽?zāi)菢颖3制聊怀A痢C端不會生效,僅手機(jī)端生效 loadingText: "請稍等, 視頻加載中......", // 視頻加載轉(zhuǎn)圈時(shí)的提示文字 loadingTimeout: 10, //當(dāng)play()的時(shí)候,如果沒有數(shù)據(jù)返回,則回調(diào) loadingTimeoutReplay: true, ///是否開啟loading超時(shí)之后自動再播放 loadingTimeoutReplayTimes: 3, //loadingTimeoutReplay 重試失敗之后,不再重新播放視頻地址。 operateBtns: { // 配置操作按鈕 其中 fullscreen: false, //全屏按鈕 screenshot: false, //截圖按鈕 play: false, //播放暫停按鈕 audio: false, //聲音按鈕 record: false, //錄制按鈕 }, recordType: "webm", //默認(rèn)錄制的視頻格式 rotate: 0, //設(shè)置旋轉(zhuǎn)角度 showBandwidth: false, // 顯示網(wǎng)速 supportDblclickFullscreen: false, // 是否支持屏幕的雙擊事件,觸發(fā)全屏,取消全屏事件。 timeout: 10, //設(shè)置超時(shí)時(shí)長, 單位秒在連接成功之前(loading)和播放中途(heart),如果超過設(shè)定時(shí)長無數(shù)據(jù)返回,則回調(diào)timeout事件 useMSE: location.hostname !== "localhost" && location.protocol !== "https:", //是否開啟MediaSource硬解碼 useWCS: location.hostname === "localhost" || location.protocol === "https", //是否開啟Webcodecs硬解碼 useWebFullScreen: false, //是否使用web全屏(旋轉(zhuǎn)90度)(只會在移動端生效)。 videoBuffer: 0, // 設(shè)置最大緩沖時(shí)長,單位秒,播放器會自動消除延遲。 wasmDecodeErrorReplay: true, // 是否開啟解碼失敗重新播放 wcsUseVideoRender: true, //webcodecs硬解碼是否通過video標(biāo)簽渲染 }, options ) ); let jessibuca = jessibucaPlayer[this._uid]; let _this = this; // 監(jiān)聽 jessibuca 初始化事件。 jessibuca.on("load", function () { // console.log("on load init"); }); // 信息,包含錯(cuò)誤信息 jessibuca.on("log", function (msg) { // console.log("on log", msg); }); // 觸發(fā)暫停事件 jessibuca.on("pause", function () { _this.playing = false; }); // 觸發(fā)播放事件 jessibuca.on("play", function () { _this.playing = true; }); // 當(dāng)前是否全屏 jessibuca.on("fullscreen", function (msg) { // console.log("on fullscreen", msg); _this.fullscreen = msg; }); // 觸發(fā)聲音事件,返回boolean值 jessibuca.on("mute", function (msg) { // console.log("on mute", msg); _this.isNotMute = !msg; }); // 當(dāng)解析出音頻信息時(shí)回調(diào),2個(gè)回調(diào)參數(shù) // numOfChannels:聲頻通道 // sampleRate 采樣率 // encTypeCode 音頻編碼類型(10:aac,7:ALAW(g711a),8:MULAW(g711u)) // encType 音頻編碼類型(字符串) jessibuca.on("audioInfo", function (msg) { // console.log("audioInfo", msg); }); let _ts = 0; // 當(dāng)前視頻幀pts,單位毫秒ms jessibuca.on("timeUpdate", function (ts) { _ts = ts; }); // 當(dāng)解析出視頻信息時(shí)回調(diào),2個(gè)回調(diào)參數(shù) //width:視頻寬 //height:視頻高 //encTypeCode 視頻編碼類型(10:h264,12:h265) //encType 視頻編碼類型(字符串) jessibuca.on("videoInfo", function (info) { // console.log("videoInfo", info); }); // 錯(cuò)誤信息 // 目前已有的錯(cuò)誤信息: // jessibuca.ERROR.playError ;播放錯(cuò)誤,url 為空的時(shí)候,調(diào)用play方法 // jessibuca.ERROR.fetchError ;http 請求失敗 // jessibuca.ERROR.websocketError; websocket 請求失敗 // jessibuca.ERROR.webcodecsH265NotSupport; webcodecs 解碼 h265 失敗 // jessibuca.ERROR.mediaSourceH265NotSupport; mediaSource 解碼 h265 失敗 // jessibuca.ERROR.wasmDecodeError ; wasm 解碼失敗 jessibuca.on("error", function (error) { // console.log("error", error); }); // 當(dāng)設(shè)定的超時(shí)時(shí)間內(nèi)無數(shù)據(jù)返回,則回調(diào) jessibuca.on("timeout", function () { // console.log("timeout"); }); // 渲染開始 jessibuca.on("start", function () { // console.log("start"); }); // 渲染性能統(tǒng)計(jì),流開始播放后回調(diào),每秒1次。 // 0: 表示卡頓 // 1: 表示流暢 // 2: 表示非常流程 jessibuca.on("performance", function (performance) { let show = "卡頓"; if (performance === 2) { show = "非常流暢"; } else if (performance === 1) { show = "流暢"; } _this.performance = show; }); // 流狀態(tài)統(tǒng)計(jì),流開始播放后回調(diào),每秒1次。 // buf: 當(dāng)前緩沖區(qū)時(shí)長,單位毫秒, // fps: 當(dāng)前視頻幀率, // abps: 當(dāng)前音頻碼率,單位byte, // vbps: 當(dāng)前視頻碼率,單位byte, // ts:當(dāng)前視頻幀pts,單位毫秒 jessibuca.on("stats", function (stats) {}); // 當(dāng)前網(wǎng)速, 單位KB 每秒1次, jessibuca.on("kBps", function (kBps) { _this.kBps = Math.round(kBps); }); }, playBtnClick: function (event) { this.play(this.videoUrl); }, play: function (url) { console.log(url); if (jessibucaPlayer[this._uid]) { this.destroy(); } this.create(); jessibucaPlayer[this._uid].on("play", () => { this.playing = true; this.loaded = true; this.quieting = jessibuca.quieting; }); if (jessibucaPlayer[this._uid].hasLoaded()) { jessibucaPlayer[this._uid].play(url); } else { jessibucaPlayer[this._uid].on("load", () => { console.log("load 播放"); jessibucaPlayer[this._uid].play(url); }); } }, pause: function () { if (jessibucaPlayer[this._uid]) { jessibucaPlayer[this._uid].pause(); } this.playing = false; this.err = ""; this.performance = ""; }, screenshot: function () { if (jessibucaPlayer[this._uid]) { jessibucaPlayer[this._uid].screenshot(); } }, mute: function () { if (jessibucaPlayer[this._uid]) { jessibucaPlayer[this._uid].mute(); } }, cancelMute: function () { if (jessibucaPlayer[this._uid]) { jessibucaPlayer[this._uid].cancelMute(); } }, destroy: function () { if (jessibucaPlayer[this._uid]) { jessibucaPlayer[this._uid].destroy(); } if (document.getElementById("buttonsBox") == null) { this.$refs.container.appendChild(this.btnDom); } jessibucaPlayer[this._uid] = null; this.playing = false; this.err = ""; this.performance = ""; }, eventcallbacK: function (type, message) {}, fullscreenSwich: function () { let isFull = this.isFullscreen(); jessibucaPlayer[this._uid].setFullscreen(!isFull); this.fullscreen = !isFull; }, isFullscreen: function () { return ( document.fullscreenElement || document.msFullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || false ); }, closeVideo: function () { this.destroy(); this.$emit("videoClose"); }, }, }; </script> <style> .buttons-box { width: 100%; height: 28px; background-color: rgba(43, 51, 63, 0.7); position: absolute; display: -webkit-box; display: -ms-flexbox; display: flex; left: 0; bottom: 0; user-select: none; z-index: 10; } .jessibuca-btn { width: 20px; color: rgb(255, 255, 255); line-height: 27px; margin: 0px 10px; padding: 0px 2px; cursor: pointer; text-align: center; font-size: 0.8rem !important; } .buttons-box-right { position: absolute; right: 0; } @font-face { font-family: "iconfont"; /* Project id 1291092 */ src: url("~@/assets/iconfont/iconfont.woff2?t=1673251105600") format("woff2"); } .iconfont { font-family: "iconfont" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-play:before { content: "\e603"; } .icon-pause:before { content: "\e6c6"; } .icon-stop:before { content: "\e6a8"; } .icon-audio-high:before { content: "\e793"; } .icon-audio-mute:before { content: "\e792"; } .icon-shuaxin11:before { content: "\e720"; } .icon-weibiaoti10:before { content: "\e78f"; } .icon-weibiaoti11:before { content: "\e790"; } .icon-camera1196054easyiconnet:before { content: "\e791"; } </style>
使用
<wk-video-player class="video" ref="player" :videoUrl="videoUrl" @videoClose="onVideoClose" /> --- videoUrl:'直播流url地址' onVideoClose() { this.$set(this.videoUrl, ""); },
小知識 引入iconfont
將iconfont 下載好的圖標(biāo) 放入assets即可,該字體已上傳
總結(jié)
到此這篇關(guān)于vue2之jessibuca視頻插件使用的文章就介紹到這了,更多相關(guān)vue2 jessibuca視頻插件使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用keep-alive進(jìn)行組件緩存方法詳解(組件不緩存問題解決)
keep-alive包裹動態(tài)組件時(shí),會緩存不活動的組件實(shí)例,而不是銷毀它們,下面這篇文章主要給大家介紹了關(guān)于vue使用keep-alive進(jìn)行組件緩存方法(組件不緩存問題解決)的相關(guān)資料,需要的朋友可以參考下2022-09-09VUE PC端可拖動懸浮按鈕的實(shí)現(xiàn)代碼
這篇文章主要介紹了VUE PC端可拖動懸浮按鈕的實(shí)現(xiàn)代碼,通過實(shí)例代碼介紹了父頁面引用的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02Vue中的scoped實(shí)現(xiàn)原理及穿透方法
這篇文章主要介紹了Vue中的scoped實(shí)現(xiàn)原理及穿透方法,本文通過實(shí)例文字相結(jié)合的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-05-05vue-echarts如何實(shí)現(xiàn)圖表組件封裝詳解
由于在項(xiàng)目中需要對數(shù)據(jù)進(jìn)行可視化處理,也就是用圖表展示,所以下面這篇文章主要給大家介紹了關(guān)于vue-echarts如何實(shí)現(xiàn)圖表組件封裝的相關(guān)資料,需要的朋友可以參考下2022-05-05elementui如何解決el-table重復(fù)寫loading問題
這篇文章主要介紹了elementui如何解決el-table重復(fù)寫loading問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08