197 lines
7.4 KiB
Vue
197 lines
7.4 KiB
Vue
<template>
|
||
<!-- #ifdef H5 -->
|
||
<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>
|
||
<!-- #endif -->
|
||
<!-- #ifdef MP -->
|
||
<live-player :src="video_src" autoplay :muted="muted" class="video-size" @statechange="statechange" @error="error" />
|
||
<!-- #endif -->
|
||
<!-- #ifdef APP -->
|
||
<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>
|
||
<!-- #endif -->
|
||
</template>
|
||
|
||
<script>
|
||
import H5HlsVideo from '@/pages/plugins/live/pull/components/h5-hls-video/h5-hls-video.vue';
|
||
import { isEmpty } from '@/common/js/common/common.js';
|
||
|
||
/**
|
||
* 直播拉流视频组件
|
||
* 支持H5、小程序和APP三种平台的视频播放
|
||
* 根据不同平台使用不同的播放器组件实现视频播放功能
|
||
*/
|
||
export default {
|
||
components: {
|
||
H5HlsVideo
|
||
},
|
||
props: {
|
||
/**
|
||
* 视频源地址
|
||
* @type {String}
|
||
* @default 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'
|
||
*/
|
||
propSrc:{
|
||
type: String,
|
||
default: 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'
|
||
}
|
||
},
|
||
watch: {
|
||
propSrc: {
|
||
handler(newVal, oldVal) {
|
||
if (newVal != oldVal) {
|
||
this.video_src = newVal;
|
||
}
|
||
},
|
||
immediate: true
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
windowWidth: 0,
|
||
windowHeight: 0,
|
||
muted: false,
|
||
video_src: '',
|
||
video_player_show: true,
|
||
error_msg_count: 0,
|
||
}
|
||
},
|
||
created() {
|
||
// 获取窗口信息,用于设置视频尺寸
|
||
const data = uni.getWindowInfo();
|
||
this.windowWidth = data.windowWidth;
|
||
this.windowHeight = data.windowHeight;
|
||
},
|
||
// #ifdef H5
|
||
mounted() {
|
||
window.addEventListener('click', this.click_video);
|
||
},
|
||
beforeDestroy() {
|
||
window.removeEventListener('click', this.click_video);
|
||
},
|
||
//#endif
|
||
methods: {
|
||
/**
|
||
* 点击视频区域处理函数
|
||
* 点击时切换视频是否静音
|
||
*/
|
||
click_video() {
|
||
this.$emit('mutedTap');
|
||
},
|
||
reload_video() {
|
||
// #ifndef MP
|
||
// 深拷贝视频源地址,避免直接修改原地址
|
||
let src = '';
|
||
if (!isEmpty(this.propSrc)) {
|
||
src = this.propSrc;
|
||
}
|
||
this.video_src = ''; // 清除原地址
|
||
this.video_player_show = false;
|
||
setTimeout(() => {
|
||
this.video_src = src; // 重新赋值
|
||
this.video_player_show = true;
|
||
this.error_msg_count = 0;
|
||
}, 100);
|
||
// #endif
|
||
},
|
||
// 视频元数据加载完成处理函数, 不太准确,有的时候是直播的中间区域状态加载完了,但是视频还没有开始播放
|
||
loadedmetadata() {
|
||
this.$emit('loadedmetadata');
|
||
},
|
||
/**
|
||
* 直播播放器状态变化处理函数(小程序平台)
|
||
* @param {Object} e - 状态变化事件对象
|
||
*/
|
||
statechange(e) {
|
||
console.log(e.detail.code);
|
||
},
|
||
|
||
/**
|
||
* 播放错误处理函数
|
||
* 根据不同平台处理播放错误,并在适当条件下触发ended事件
|
||
* @param {Object} e - 错误事件对象
|
||
*/
|
||
error(e) {
|
||
// 只有组件显示时才触发这个事件
|
||
if (this.video_player_show) {
|
||
// #ifdef H5
|
||
// 非初次加载错误的, 直播结束
|
||
if (e.type != 'otherError' || e.details != 'internalException') {
|
||
// 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');
|
||
}
|
||
}
|
||
// #endif
|
||
// #ifdef APP-NVUE
|
||
if (!isEmpty(e.type) && e.type == 'error') {
|
||
this.$emit('ended');
|
||
}
|
||
// #endif
|
||
console.log(e, 'error');
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 视频播放结束处理函数
|
||
* 当视频播放完成时触发ended事件通知父组件
|
||
*/
|
||
// video app使用这种方式,判断直播是否结束
|
||
ended() {
|
||
this.$emit('ended');
|
||
},
|
||
|
||
//#ifdef H5
|
||
/**
|
||
* H5平台自动播放成功处理函数
|
||
* 当静音自动播放成功时触发mutedAutoPlaySuccess事件
|
||
* @param {Boolean} e - 是否自动播放成功
|
||
*/
|
||
// 网页有的时候直接访问会报错,所以这里需要判断一下,如果报错则静音播放,静音播放成功添加提示,用户操作之后改为非静音播放
|
||
// 静音自动播放成功, 触发事件, 添加提示弹出框,用户操作之后改为非静音播放
|
||
auto_play_success(e) {
|
||
// 静音播放成功时,触发事件,提示用户需要修改点击修改播放状态
|
||
if (e) {
|
||
this.$emit('mutedAutoPlaySuccess');
|
||
}
|
||
},
|
||
|
||
/**
|
||
* H5平台自动播放失败处理函数
|
||
* 当自动播放失败时,设置为静音状态重新尝试播放
|
||
* @param {Boolean} e - 是否自动播放失败
|
||
*/
|
||
// 自动播放失败, 静音播放
|
||
auto_play_error(e) {
|
||
// 播放失败,并且是非静音状态,则静音播放尝试是否成功
|
||
if (!e) {
|
||
this.muted = true;
|
||
}
|
||
},
|
||
|
||
/**
|
||
* H5平台静音状态切换函数
|
||
* 用户点击后取消静音状态
|
||
*/
|
||
// 静音提示点击
|
||
muted_tap() {
|
||
this.muted = false;
|
||
}
|
||
// #endif
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.video-size {
|
||
width: 100%;
|
||
height: 100vh;
|
||
}
|
||
.video-bg {
|
||
background-image: linear-gradient(to bottom,#ba623c,#14766a);
|
||
}
|
||
</style> |