在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)聽:當配置變化時重新初始化播放器
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?element實現(xiàn)權(quán)限管理業(yè)務(wù)流程詳解
目前本人再使用vue-element-admin項目時都是通過直接刪除一些用不上的路由來進行側(cè)邊欄的清除,但是其實有一個更加好的辦法來對項目的側(cè)邊欄顯示的內(nèi)用進行管理,就是權(quán)限管理,其實也不知道這個方法好不好,原理上來說時跟直接刪除該路由的方式時一樣的2022-08-08
vue+elementUI 實現(xiàn)內(nèi)容區(qū)域高度自適應(yīng)的示例
這篇文章主要介紹了vue+elementUI 實現(xiàn)內(nèi)容區(qū)域高度自適應(yīng)的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-09-09
Vue.js表單標簽中的單選按鈕、復(fù)選按鈕和下拉列表的取值問題
這篇文章主要介紹了Vue.js表單標簽中的單選按鈕、復(fù)選按鈕和下拉列表的取值問題,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11

