在Vue3中使用EasyPlayer.js播放器的具體流程
前言
隨著技術(shù)的發(fā)展,越來(lái)越多的H5流媒體播放器開(kāi)始支持H.265編碼格式。例如,EasyPlayer.js播放器能夠支持H.264、H.265等多種音視頻編碼格式,這使得播放器能夠適應(yīng)不同的視頻內(nèi)容和網(wǎng)絡(luò)環(huán)境。
在Vue3中如何使用EasyPlayer.js播放器?具體流程如下:
1)首先通過(guò)npm引入easyplayer.js;
npm install @easydarwin/easyplayer
2)然后找到項(xiàng)目node_modules中的easydarwin,如下:
3)逐級(jí)點(diǎn)擊easyplayer->dist->element;
4)找到EasyPlayer-element.min.js、EasyPlayer.wasm,將這兩個(gè)文件復(fù)制到項(xiàng)目的根目錄下;
5)在項(xiàng)目的入口文件index.html中,通過(guò)script標(biāo)簽引入EasyPlayer-element.min.js,如下圖:
6)完成以上操作后,就可以在vue組件中直接使用EasyPlayer播放器了。
注意:如果需要使用到快照功能,需要先獲取播放器easyplayer的vue實(shí)例,然后通過(guò)實(shí)例去調(diào)用snapshot方法。
EasyPlayer屬于一款高效、精煉、穩(wěn)定且免費(fèi)的流媒體播放器,可支持多種流媒體協(xié)議播放,無(wú)須安裝任何插件,起播快、延遲低、兼容性強(qiáng),使用非常便捷,并且已實(shí)現(xiàn)網(wǎng)頁(yè)端實(shí)時(shí)錄像、在iOS上實(shí)現(xiàn)低延時(shí)直播等功能。
H5流媒體播放器如EasyPlayer.js支持多種流媒體協(xié)議播放,無(wú)需安裝任何插件,即可在瀏覽器中直接播放視頻流。H5播放器不僅支持直播和點(diǎn)播播放,還具備錄像、快照截圖、MP4播放、多屏播放、倍數(shù)播放、全屏播放等功能特性。
H5流媒體播放器還具有跨平臺(tái)兼容性的優(yōu)勢(shì),能夠無(wú)縫地運(yùn)行在谷歌瀏覽器、火狐瀏覽器等主流瀏覽器上,為用戶(hù)提供一致的使用體驗(yàn)。
附:vue3+easyplayer封裝組件
使用easyplayer.js版本為 https://github.com/EasyDarwin/EasyPlayer.js/tree/main
由于new easyplayer生成實(shí)例需要一段時(shí)間才能進(jìn)行播放url,所以不斷請(qǐng)求play方法,或者設(shè)置按鈕手動(dòng)點(diǎn)擊開(kāi)始播放
由于監(jiān)聽(tīng)不到截圖回調(diào)的事件,使用點(diǎn)擊監(jiān)聽(tīng)元素,手動(dòng)觸發(fā)截圖功能并調(diào)用自身邏輯
自定義禁用右鍵彈窗信息
<template> <div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%"> <slot name="header" v-if="!fullscreen"></slot> <div class="player-wrapper"> <!-- 播放器容器 --> <div ref="playerContainer" class="player-box" @contextmenu="contextmenu"> <div class="no-data" v-if="noData">{{ attrs.alt }}</div> <slot name="header" v-if="fullscreen"></slot> <slot></slot> </div> </div> </div> </template> <script lang="ts" setup> import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'; // 接收父組件的動(dòng)態(tài)屬性(包括所有配置項(xiàng)) type easyPlayerProps = { alt?: string; // 無(wú)數(shù)據(jù)時(shí)顯示的文本 videoUrl: string; // 視頻地址 isLive?: boolean; // 是否直播 hasAudio?: boolean; // 是否解析音頻 isMute?: boolean; // 是否靜音 stretch?: boolean; // 是否拉伸視頻 bufferTime?: number; // 緩沖時(shí)間 loadTimeOut?: number; // 加載超時(shí)時(shí)間 loadTimeReplay?: number; // 重連次數(shù) MSE?: boolean; // MSE 模式 WCS?: boolean; // WCS 模式 WASM?: boolean; // WASM 模式 isReplay?: boolean; // 是否回放 gpuDecoder?: boolean; // 硬解碼 watermark?: object | null; // 水印配置 fullWatermark?: object | null; // 全屏水印 debug?: boolean; // 是否打印日志 }; const attrs = withDefaults(defineProps<easyPlayerProps>(), { isLive: true, hasAudio: true, isMute: false, stretch: true, isReplay: false, bufferTime: 1, loadTimeOut: 30, loadTimeReplay: 3, MSE: false, WCS: true, WASM: false, gpuDecoder: false, watermark: null, fullWatermark: null, debug: false, videoUrl: '' }); const emits = defineEmits<{ (e: 'fullscreen', data: any): void; (e: 'snapInside', data: any): void; (e: 'customButtons', data: any): void; (e: 'videoInfo', data: any): void; }>(); // 播放器 DOM 容器引用 const playerContainer = ref<HTMLDivElement | null>(null); let playerInstance: any = null; // 播放器實(shí)例 const noData = ref(true); // 是否無(wú)數(shù)據(jù) // 配置與狀態(tài) const config = reactive({ isLive: attrs.isLive, hasAudio: attrs.hasAudio, isMute: attrs.isMute, stretch: attrs.stretch, bufferTime: attrs.bufferTime, loadTimeOut: attrs.loadTimeOut, loadTimeReplay: attrs.loadTimeReplay, MSE: attrs.MSE, WCS: attrs.WCS, WASM: attrs.WASM, gpuDecoder: attrs.gpuDecoder, watermark: attrs.watermark, fullWatermark: attrs.fullWatermark, debug: attrs.debug }); const fullscreen = ref(false); let isPlay = false; // 初始化播放器 const initializePlayer = () => { if (playerContainer.value) { playerInstance = new (window as any).EasyPlayerPro(playerContainer.value, { isLive: config.isLive, hasAudio: config.hasAudio, isMute: config.isMute, stretch: config.stretch, bufferTime: config.bufferTime, loadTimeOut: config.loadTimeOut, loadTimeReplay: config.loadTimeReplay, MSE: config.MSE, WCS: config.WCS, WASM: config.WASM, gpuDecoder: config.gpuDecoder, watermark: config.watermark, fullWatermark: config.fullWatermark, debug: config.debug }); console.log('播放器實(shí)例', playerInstance); // 事件監(jiān)聽(tīng) playerInstance.on('fullscreen', (status: boolean) => { console.log('全屏', status); fullscreen.value = status; emits('fullscreen', status); }); playerInstance.on('videoInfo', (data: any) => { isPlay = true; playerContainer.value?.querySelector('.easyplayer-icon-screenshot')?.addEventListener('click', screenshot); emits('videoInfo', data); if (!attrs.isReplay) { return; } // 獲取子元素 const childElement = document.querySelector('.easyplayer-record'); if (childElement) { // 向上遍歷兩層父節(jié)點(diǎn)(根據(jù)實(shí)際HTML結(jié)構(gòu)) const parentContainer = childElement.parentNode; // 確保父容器存在且是HTMLElement if (parentContainer instanceof HTMLElement) { parentContainer.style.display = 'none'; // 安全地設(shè)置樣式 } } }); playerInstance.on('timeout', (error: any) => console.error('timeout:', error)); playerInstance.on('recordStart', () => { emits('customButtons', '錄像'); }); playerInstance.on('recordEnd', () => { emits('customButtons', '錄像'); }); playerInstance.on('error', (error: any) => { console.error('播放錯(cuò)誤:', error); destroyPlayer(); }); } }; // 鼠標(biāo)右鍵事件隱藏 const contextmenu = () => { nextTick(() => { let playBtn = playerContainer.value?.querySelector('.easyplayer-contextmenu-btn') as any; playBtn?.remove(); }); }; const screenshot = () => { const base64 = playerInstance.screenshot('', 'png', 0.2, 'base64'); emits('snapInside', base64); }; let timeout: any = null; // 銷(xiāo)毀播放器 const destroyPlayer = () => { return new Promise(resolve => { if (playerInstance) { playerContainer.value?.querySelector('.easyplayer-icon-screenshot')?.removeEventListener('click', screenshot); playerInstance.destroy(); playerInstance = null; } isPlay = false; clearTimeout(timeout); setTimeout(() => { resolve(null); }, 100); }); }; //重播 const onReplay = () => { destroyPlayer().then(() => { initializePlayer(); play(); }); }; // 播放功能 const play = () => { console.log('播放視頻', attrs.videoUrl); noData.value = false; setTimeout( url => { playerInstance && playerInstance .play(url) .then(() => { if (playerContainer.value) { let playBtn = playerContainer.value.querySelector('.easyplayer-play') as any; playBtn.style = 'display:block'; } timeout = setTimeout(() => { console.log(isPlay); if (!isPlay) { play(); } }, 1000); }) .catch((error: any) => { console.error('播放失敗:', error); }); }, 100, attrs.videoUrl ); }; // 暫停功能 const pause = () => { playerInstance?.pause(); }; // 靜音功能 const toggleMute = () => { const isMuted = playerInstance?.isMute(); playerInstance?.setMute(!isMuted); }; // 全屏功能 const toggleFullscreen = () => { playerInstance?.setFullscreen(); }; // 屬性監(jiān)聽(tīng):當(dāng)配置變化時(shí)重新初始化播放器 watch( () => attrs.videoUrl, newVal => { console.log(newVal, playerInstance); if (newVal) { onReplay(); } else { noData.value = true; destroyPlayer(); } }, { deep: true } ); // 生命周期管理 onMounted(() => { if (attrs.videoUrl) { initializePlayer(); play(); } }); onBeforeUnmount(() => { destroyPlayer(); }); // 暴露方法供父組件調(diào)用 defineExpose({ pause, onReplay, play, toggleMute, toggleFullscreen, stop, destroyPlayer }); </script> <style scoped> .player-wrapper { position: absolute; width: 100%; height: 100%; margin: auto; } .player-box { position: relative; width: 100%; height: 100%; background-color: black; } .no-data { position: absolute; top: 50%; left: 50%; z-index: 999; font-size: 16px; color: #ffffff; transform: translate(-50%, -50%); } </style>
總結(jié)
到此這篇關(guān)于在Vue3中使用EasyPlayer.js播放器的文章就介紹到這了,更多相關(guān)Vue3使用EasyPlayer.js播放器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue利用computer解決單項(xiàng)數(shù)據(jù)流的問(wèn)題詳解
Vue 是一個(gè)非常流行和強(qiáng)大的前端框架,它讓我們可以用簡(jiǎn)潔和優(yōu)雅的方式來(lái)構(gòu)建用戶(hù)界面,今天我們來(lái)分享一個(gè) Vue 中非常經(jīng)典的問(wèn)題,也是一個(gè)非常實(shí)用的技巧,希望對(duì)大家有所幫助2023-07-07詳解vue數(shù)據(jù)響應(yīng)式原理之?dāng)?shù)組
這篇文章主要為大家詳細(xì)介紹了vue數(shù)據(jù)響應(yīng)式原理之?dāng)?shù)組,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02vue組件props屬性監(jiān)聽(tīng)不到值變化問(wèn)題
這篇文章主要介紹了vue組件props屬性監(jiān)聽(tīng)不到值變化問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue?axios庫(kù)發(fā)送請(qǐng)求的示例介紹
axios是基于promise的HTTP庫(kù),可以使用在瀏覽器和node.js中,它不是vue的第三方插件,vue-axios是axios集成到Vue.js的小包裝器,可以像插件一樣安裝使用:Vue.use(VueAxios,?axios),本文給大家介紹Vue?axios和vue-axios關(guān)系,感興趣的朋友一起看看吧2022-08-08vue實(shí)現(xiàn).md文件預(yù)覽功能的兩種方法詳解
這篇文章主要介紹了Vue預(yù)覽.md文件的兩種方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2025-04-04關(guān)于怎么在vue項(xiàng)目里寫(xiě)react詳情
本篇文章是在vue項(xiàng)目里寫(xiě)tsx的一篇介紹。其實(shí)vue里面寫(xiě)jsx也挺有意思的,接下來(lái)小編九給大家詳細(xì)介紹吧,感興趣的小伙伴請(qǐng)參考下面的文章內(nèi)容2021-09-09vue中調(diào)接口的方式詳解this.$api、直接調(diào)用、axios
這篇文章主要介紹了vue中調(diào)接口的方式:this.$api、直接調(diào)用、axios,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11