在Vue3中使用EasyPlayer.js播放器的具體流程
前言
隨著技術(shù)的發(fā)展,越來越多的H5流媒體播放器開始支持H.265編碼格式。例如,EasyPlayer.js播放器能夠支持H.264、H.265等多種音視頻編碼格式,這使得播放器能夠適應(yīng)不同的視頻內(nèi)容和網(wǎng)絡(luò)環(huán)境。
在Vue3中如何使用EasyPlayer.js播放器?具體流程如下:
1)首先通過npm引入easyplayer.js;
npm install @easydarwin/easyplayer
2)然后找到項目node_modules中的easydarwin,如下:
3)逐級點擊easyplayer->dist->element;
4)找到EasyPlayer-element.min.js、EasyPlayer.wasm,將這兩個文件復(fù)制到項目的根目錄下;
5)在項目的入口文件index.html中,通過script標簽引入EasyPlayer-element.min.js,如下圖:
6)完成以上操作后,就可以在vue組件中直接使用EasyPlayer播放器了。
注意:如果需要使用到快照功能,需要先獲取播放器easyplayer的vue實例,然后通過實例去調(diào)用snapshot方法。
EasyPlayer屬于一款高效、精煉、穩(wěn)定且免費的流媒體播放器,可支持多種流媒體協(xié)議播放,無須安裝任何插件,起播快、延遲低、兼容性強,使用非常便捷,并且已實現(xiàn)網(wǎng)頁端實時錄像、在iOS上實現(xiàn)低延時直播等功能。
H5流媒體播放器如EasyPlayer.js支持多種流媒體協(xié)議播放,無需安裝任何插件,即可在瀏覽器中直接播放視頻流。H5播放器不僅支持直播和點播播放,還具備錄像、快照截圖、MP4播放、多屏播放、倍數(shù)播放、全屏播放等功能特性。
H5流媒體播放器還具有跨平臺兼容性的優(yōu)勢,能夠無縫地運行在谷歌瀏覽器、火狐瀏覽器等主流瀏覽器上,為用戶提供一致的使用體驗。
附:vue3+easyplayer封裝組件
使用easyplayer.js版本為 https://github.com/EasyDarwin/EasyPlayer.js/tree/main
由于new easyplayer生成實例需要一段時間才能進行播放url,所以不斷請求play方法,或者設(shè)置按鈕手動點擊開始播放
由于監(jiān)聽不到截圖回調(diào)的事件,使用點擊監(jiān)聽元素,手動觸發(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'; // 接收父組件的動態(tài)屬性(包括所有配置項) type easyPlayerProps = { alt?: string; // 無數(shù)據(jù)時顯示的文本 videoUrl: string; // 視頻地址 isLive?: boolean; // 是否直播 hasAudio?: boolean; // 是否解析音頻 isMute?: boolean; // 是否靜音 stretch?: boolean; // 是否拉伸視頻 bufferTime?: number; // 緩沖時間 loadTimeOut?: number; // 加載超時時間 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; // 播放器實例 const noData = ref(true); // 是否無數(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('播放器實例', playerInstance); // 事件監(jiān)聽 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é)點(根據(jù)實際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('播放錯誤:', error); destroyPlayer(); }); } }; // 鼠標右鍵事件隱藏 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; // 銷毀播放器 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)聽:當(dāng)配置變化時重新初始化播放器 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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue利用computer解決單項數(shù)據(jù)流的問題詳解
Vue 是一個非常流行和強大的前端框架,它讓我們可以用簡潔和優(yōu)雅的方式來構(gòu)建用戶界面,今天我們來分享一個 Vue 中非常經(jīng)典的問題,也是一個非常實用的技巧,希望對大家有所幫助2023-07-07詳解vue數(shù)據(jù)響應(yīng)式原理之?dāng)?shù)組
這篇文章主要為大家詳細介紹了vue數(shù)據(jù)響應(yīng)式原理之?dāng)?shù)組,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02vue實現(xiàn).md文件預(yù)覽功能的兩種方法詳解
這篇文章主要介紹了Vue預(yù)覽.md文件的兩種方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2025-04-04vue中調(diào)接口的方式詳解this.$api、直接調(diào)用、axios
這篇文章主要介紹了vue中調(diào)接口的方式:this.$api、直接調(diào)用、axios,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11