vr-shopxo-uniapp/pages/plugins/live/pull/components/video/video.vue

182 lines
6.9 KiB
Vue
Raw Normal View History

2025-11-27 09:28:46 +00:00
<template>
<!-- #ifdef H5 -->
2025-12-17 07:07:36 +00:00
<h5-hls-video v-if="video_player_show" :propSrc="video_src" propAutoplay :propMuted="muted" class="video-size" @hlsError="error" @ended="ended" @loadedmetadata="loadedmetadata" @autoPlaySuccess="auto_play_success" @autoPlayError="auto_play_error"></h5-hls-video>
2025-11-27 09:28:46 +00:00
<!-- #endif -->
<!-- #ifdef MP -->
2025-12-15 07:25:15 +00:00
<live-player :src="video_src" autoplay :muted="muted" class="video-size" @statechange="statechange" @error="error" />
2025-11-27 09:28:46 +00:00
<!-- #endif -->
<!-- #ifdef APP -->
2025-12-17 07:07:36 +00:00
<video v-if="video_player_show" :src="video_src" autoplay :is-video="true" :controls="false" :muted="muted" object-fit="contain" :style="{'width': windowWidth + 'px', 'height': windowHeight + 'px', 'background-color': 'transparent'}" @play="loadedmetadata" @error="error" @ended="ended"></video>
2025-11-27 09:28:46 +00:00
<!-- #endif -->
</template>
<script>
2025-11-28 06:09:09 +00:00
import H5HlsVideo from '@/pages/plugins/live/pull/components/h5-hls-video/h5-hls-video.vue';
2025-11-28 09:20:46 +00:00
import { isEmpty } from '@/common/js/common/common.js';
2025-12-05 09:31:05 +00:00
/**
* 直播拉流视频组件
* 支持H5小程序和APP三种平台的视频播放
* 根据不同平台使用不同的播放器组件实现视频播放功能
*/
2025-11-27 09:28:46 +00:00
export default {
2025-11-28 06:09:09 +00:00
components: {
H5HlsVideo
},
2025-11-27 09:28:46 +00:00
props: {
2025-12-05 09:31:05 +00:00
/**
* 视频源地址
* @type {String}
* @default 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'
*/
2025-12-04 10:14:59 +00:00
propSrc:{
2025-11-27 09:28:46 +00:00
type: String,
default: 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'
}
},
2025-12-15 07:25:15 +00:00
watch: {
propSrc: {
handler(newVal, oldVal) {
if (newVal != oldVal) {
this.video_src = newVal;
}
},
immediate: true
}
},
2025-11-27 09:28:46 +00:00
data() {
return {
windowWidth: 0,
windowHeight: 0,
muted: false,
2025-12-15 08:33:12 +00:00
video_src: '',
video_player_show: true,
2025-12-19 02:42:44 +00:00
error_msg_count: 0,
2025-11-27 09:28:46 +00:00
}
},
created() {
2025-12-05 09:31:05 +00:00
// 获取窗口信息,用于设置视频尺寸
2025-11-27 09:28:46 +00:00
const data = uni.getWindowInfo();
this.windowWidth = data.windowWidth;
this.windowHeight = data.windowHeight;
},
methods: {
2025-12-15 07:25:15 +00:00
reload_video() {
// #ifndef MP
// 深拷贝视频源地址,避免直接修改原地址
2025-12-15 08:33:12 +00:00
let src = '';
if (!isEmpty(this.propSrc)) {
src = this.propSrc;
}
2025-12-15 07:25:15 +00:00
this.video_src = ''; // 清除原地址
2025-12-15 08:33:12 +00:00
this.video_player_show = false;
2025-12-15 07:25:15 +00:00
setTimeout(() => {
this.video_src = src; // 重新赋值
2025-12-15 08:33:12 +00:00
this.video_player_show = true;
2025-12-19 02:42:44 +00:00
this.error_msg_count = 0;
2025-12-15 07:25:15 +00:00
}, 100);
// #endif
},
// 视频元数据加载完成处理函数, 不太准确,有的时候是直播的中间区域状态加载完了,但是视频还没有开始播放
loadedmetadata() {
this.$emit('loadedmetadata');
},
2025-12-05 09:31:05 +00:00
/**
* 直播播放器状态变化处理函数小程序平台
* @param {Object} e - 状态变化事件对象
*/
2025-11-27 09:28:46 +00:00
statechange(e) {
console.log(e.detail.code);
},
2025-12-05 09:31:05 +00:00
/**
* 播放错误处理函数
* 根据不同平台处理播放错误并在适当条件下触发ended事件
* @param {Object} e - 错误事件对象
*/
2025-11-27 09:28:46 +00:00
error(e) {
2025-12-15 08:33:12 +00:00
// 只有组件显示时才触发这个事件
if (this.video_player_show) {
// #ifdef H5
// 非初次加载错误的, 直播结束
if (e.type != 'otherError' || e.details != 'internalException') {
2025-12-19 02:42:44 +00:00
// 3次切片报错之后认为直播结束
if (e.details == 'levelLoadError') {
this.error_msg_count++;
if (this.error_msg_count > 2) {
this.error_msg_count = 0;
this.$emit('ended');
}
} else {
this.$emit('ended');
}
2025-12-15 08:33:12 +00:00
}
// #endif
// #ifdef APP-NVUE
if (!isEmpty(e.type) && e.type == 'error') {
this.$emit('ended');
}
// #endif
console.log(e, 'error');
2025-11-28 10:19:51 +00:00
}
2025-11-27 09:28:46 +00:00
},
2025-12-05 09:31:05 +00:00
/**
* 视频播放结束处理函数
* 当视频播放完成时触发ended事件通知父组件
*/
2025-11-27 09:28:46 +00:00
// video app使用这种方式判断直播是否结束
ended() {
2025-11-28 06:46:57 +00:00
this.$emit('ended');
},
2025-12-05 09:31:05 +00:00
2025-12-01 06:37:56 +00:00
//#ifdef H5
2025-12-05 09:31:05 +00:00
/**
* H5平台自动播放成功处理函数
* 当静音自动播放成功时触发mutedAutoPlaySuccess事件
* @param {Boolean} e - 是否自动播放成功
*/
2025-12-01 06:37:56 +00:00
// 网页有的时候直接访问会报错,所以这里需要判断一下,如果报错则静音播放,静音播放成功添加提示,用户操作之后改为非静音播放
// 静音自动播放成功, 触发事件, 添加提示弹出框,用户操作之后改为非静音播放
auto_play_success(e) {
// 静音播放成功时,触发事件,提示用户需要修改点击修改播放状态
if (e) {
this.$emit('mutedAutoPlaySuccess');
}
},
2025-12-05 09:31:05 +00:00
/**
* H5平台自动播放失败处理函数
* 当自动播放失败时设置为静音状态重新尝试播放
* @param {Boolean} e - 是否自动播放失败
*/
// 自动播放失败, 静音播放
auto_play_error(e) {
// 播放失败,并且是非静音状态,则静音播放尝试是否成功
if (!e) {
this.muted = true;
}
},
2025-12-05 09:31:05 +00:00
/**
* H5平台静音状态切换函数
* 用户点击后取消静音状态
*/
// 静音提示点击
muted_tap() {
this.muted = false;
2025-11-27 09:28:46 +00:00
}
2025-12-01 06:37:56 +00:00
// #endif
2025-11-27 09:28:46 +00:00
},
}
</script>
2025-11-28 09:20:46 +00:00
<style lang="scss" scoped>
2025-11-27 09:28:46 +00:00
.video-size {
width: 100vw;
height: 100vh;
}
2025-11-28 10:19:51 +00:00
.video-bg {
background-image: linear-gradient(to bottom,#ba623c,#14766a);
}
2025-11-27 09:28:46 +00:00
</style>