EasyPlayerPro播放本地MP4视频

devtools/2024/11/29 8:55:29/

加载本地mp4需指定协议http://localhost:5100/(如 http:https:webrtc:ws: 等)来正确处理媒体流。

目录结构

├── public/

│   ├──static

│   │   ├── video.mp4

├── components/

│   ├── EasyWebRTC.vue

├── views/

│   ├── test/

│   │   ├── index.vue

组件封装

javascript"><template><div class="easy-player-container"><!-- 为每个播放器容器添加唯一的类 --><div id="player_box1" class="player-box"></div></div>
</template><script>
/* global EasyPlayerPro */
export default {name: 'EasyPlayerPro',props: {initialConfig: {type: Object,default: () => ({}),},},data () {return {player: '',playerInstances: {}, // 存储播放器实例config: {hasAudio: true,isLive: true,MSE: false,WCS: false,demuxType: 'auto',...this.initialConfig,},};},methods: {setVideoUrl (url, id, changeId) {const resolveUrl = (url) => {if (url.startsWith('http:') ||url.startsWith('https:') ||url.startsWith('webrtc:') ||url.startsWith('ws:') ||url.startsWith('wss:') ||url.startsWith('wt:') ||url.startsWith('artc:')) {return url;}const baseUrl = `${window.location.protocol}//${window.location.host}`;return `${baseUrl}${url}`;};// 转换 URLconst resolvedUrl = resolveUrl(url);console.log(`解析后的 URL: ${resolvedUrl}`);if (!resolvedUrl) {console.error('URL 不能为空');return;}// 动态设置 demuxTypelet demuxType = 'auto'; // 默认值if (url.endsWith('.mp4')) {demuxType = 'mp4';} else if (url.startsWith('webrtc://')) {demuxType = 'native'; // WebRTC 流} else if (url.startsWith('ws://') || url.startsWith('wss://')) {demuxType = 'flv'; // WebSocket 流通常为 FLV}// 更新播放器配置this.config = {...this.config,demuxType,isLive: url.startsWith('webrtc://') || url.includes('live'),};const player = this.playerInstances[id];if (player) {player.play(resolvedUrl).catch((e) => {console.error(`播放失败 (播放器${id}):`, e);this.$emit('play-error', e);});} else {// 使用箭头函数确保上下文this.$nextTick(() => {this.createPlayer(id, resolvedUrl);});}},createPlayer (id, url) {const container = document.getElementById(id);if (!container) {console.error(`未找到容器, ID: ${id}`);return;}const player = new EasyPlayerPro(container, {demuxType: this.config.demuxType || 'auto',autoplay: this.config.autoplay || true,muted: this.config.muted || true,isLive: this.config.isLive || true,});player.play(url).then(() => {console.log(`播放成功: ${url}`);this.$emit('play-started', id);}).catch((e) => {console.error(`播放失败: ${e.message || e}`, e);this.$emit('play-error', { id, error: e });});// 添加事件监听器:循环播放player.on('ended', () => {console.log(`播放结束,准备循环播放: ${url}`);player.play(url).catch((e) => {console.error(`循环播放失败: ${e.message || e}`, e);});});this.playerInstances[id] = player;// 添加事件解除静音document.addEventListener('click', () => {player.unmute(); // 用户交互后解除静音});},// 销毁所有播放器实例destroyAllPlayers () {Object.keys(this.playerInstances).forEach(id => {this.destroyPlayer(id);});},// 销毁单个播放器实例destroyPlayer (id) {const player = this.playerInstances[id];if (player) {player.destroy();delete this.playerInstances[id];}},handleUnmute () {Object.values(this.playerInstances).forEach((player) => {if (player) {player.unmute();}});},},beforeUnmount () {// 销毁所有播放器实例this.destroyAllPlayers();// 清除全局事件监听器document.removeEventListener('click', this.handleUnmute);},};
</script><style scoped>
.easy-player-container {width: 100%;background: #000;height: 100%;position: relative;
}.player-box {background: #000;
}
</style>

应用:

javascript"><template><div class="video-content"><EasyWebRTC ref="baseVideoRef":initialConfig="{ demuxType: 'native', isLive: false, hasAudio: true, autoplay: true, muted: true }"></EasyWebRTC><EasyWebRTC ref="videoRef" :initialConfig="{ demuxType: 'flv', isLive: true, hasAudio: true, }"></EasyWebRTC></div>
</template>
<script setup>
import { ref, onMounted, nextTick } from "vue";
import EasyWebRTC from "../components/EasyWebRTC.vue";// 定义组件引用
const baseVideoRef = ref(null);
const videoRef = ref(null);onMounted(() => {nextTick(() => {// 配置 baseVideoRefif (baseVideoRef.value) {const baseVideoUrl = "/video.mp4"; // 替换为实际的视频文件路径const baseContainerId = "baseVideo";try {baseVideoRef.value.setVideoUrl(baseVideoUrl, baseContainerId, baseContainerId);console.log("baseVideoRef:", baseVideoRef.value);// 修改 DOM 元素 IDconst targetChild = baseVideoRef.value.$el?.firstElementChild;if (targetChild) {targetChild.id = baseContainerId; // 修改 IDconsole.log(`成功修改 baseVideo 的 ID 为: ${baseContainerId}`);} else {console.warn("未找到 baseVideoRef 的子节点");}} catch (error) {console.error("设置 baseVideo URL 时出错:", error);}} else {console.error("baseVideoRef 未挂载");}// 配置 videoRefif (videoRef.value) {const videoUrl = "http://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-360p.mp4";const videoContainerId = "video";try {videoRef.value.setVideoUrl(videoUrl, videoContainerId, videoContainerId);// 修改父元素中的 IDconst parentElement = document.querySelector(".video-content");if (parentElement) {const targetChild = parentElement.querySelector("#player_box1");if (targetChild) {targetChild.id = videoContainerId; // 修改 IDconsole.log(`成功修改 video 的 ID 为: ${videoContainerId}`);} else {console.warn("未找到 ID 为 'player_box1' 的子节点");}} else {console.warn("未找到父元素 .video-content");}} catch (error) {console.error("设置 video URL 时出错:", error);}} else {console.error("videoRef 未挂载");}});
});
</script>
<style>
.video-content {width: 100%;height: 100vh;display: flex;flex-direction: column;justify-content: space-between;
}
</style>

效果:


http://www.ppmy.cn/devtools/137880.html

相关文章

网络原理->DNS协议和NAT协议解

前言 大家好我是小帅&#xff0c;今天我们来了解应用层的DNS协议和NAT技术 个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G 文章目录 1.重要应⽤层协议DNS(Domain Name System)1.1 DNS背景 2. NAT技术3. 总结 1.重要应⽤层协议DNS(Domain Name System) DNS是⼀整套从域…

基于Qt实现的自定义树结构容器:设计与应用

在Qt框架中&#xff0c;尽管其提供了许多强大的容器类&#xff08;如 QList, QMap, QTreeWidget 等&#xff09;&#xff0c;但缺少一个通用的、灵活的树结构容器&#xff0c;直接支持多层级数据管理。为了满足这些需求&#xff0c;本文设计并实现了一个可复用的自定义树结构容…

Opencv+ROS实现摄像头读取处理画面信息

一、工具 ubuntu18.04 ROSopencv2 编译器&#xff1a;Visual Studio Code 二、原理 图像信息 ROS数据形式&#xff1a;sensor_msgs::Image OpenCV数据形式&#xff1a;cv:Mat 通过cv_bridge()函数进行ROS向opencv转换 cv_bridge是在ROS图像消息和OpenCV图像之间进行转…

Spring Events 最新详解(spring4.2前后变化)

事件驱动设计模式&#xff0c;也可能通过Spring来实现。 围绕事件的三个角色&#xff1a; 事件&#xff08;Event&#xff09;事件发布者&#xff08;Publisher&#xff09;事件监听者&#xff08;Listener&#xff09; 文章内容&#xff1a; Spring Event.jpg 1. Demo-01:…

15 go语言(golang) - 并发编程goroutine原理及数据安全

底层原理 Go 的 goroutine 是一种轻量级的线程实现&#xff0c;允许我们在程序中并发地执行函数。与传统的操作系统线程相比&#xff0c;goroutine 更加高效和易于使用。 轻量级调度 用户态调度&#xff1a;Go 运行时提供了自己的调度器&#xff0c;这意味着 goroutine 的创建…

C++:探索哈希表秘密之哈希桶实现哈希

文章目录 前言一、链地址法概念二、哈希表扩容三、哈希桶插入逻辑四、析构函数五、删除逻辑六、查找七、链地址法代码实现总结 前言 前面我们用开放定址法代码实现了哈希表&#xff1a; C&#xff1a;揭秘哈希&#xff1a;提升查找效率的终极技巧_1 对于开放定址法来说&#…

JavaScript 对象

JavaScript 对象 一、对象是什么 JavaScript 对象是一种复合数据类型&#xff0c;它将相关的数据&#xff08;属性&#xff09;和操作这些数据的方法&#xff08;函数&#xff09;组合在一起。 二、特点 属性多样性&#xff1a;可以包含各种类型的数据作为属性。方法灵活性…

自动控制原理——BliBli站_DR_CAN

自动控制 2 稳定性分析 极点在左半平面 输入为单位冲击&#xff0c;而拉普拉斯变换为1&#xff1b;因此&#xff0c;开环和闭环系统&#xff0c;研究其传递函数的稳定性就可以了 2.5_非零初始条件下的传递函数_含有初始条件的传递函数 如果一个系统的初始条件不为0&#xff0…