修改直播状态更新

master
于肖磊 2025-12-15 16:33:12 +08:00
parent ad86f4c244
commit 1ecc88b5d9
5 changed files with 119 additions and 60 deletions

View File

@ -620,7 +620,7 @@
this.scroll_to_lower();
});
break;
case 'live-status':
case 'pull-live-room-info': //
this.$emit('liveStatus', data.content);
break;
}
@ -647,6 +647,14 @@
this.ping_timer = null;
}
},
/**
* WebSocket获取直播间数据
*/
socket_connect() {
//
this.socket_send('pull-live-room-info');
},
/**
* 发送WebSocket消息

View File

@ -1,6 +1,6 @@
<template>
<!-- #ifdef H5 -->
<h5-hls-video ref="videoPlayer" :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>
<h5-hls-video ref="videoPlayer" 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" />
@ -49,7 +49,8 @@
windowWidth: 0,
windowHeight: 0,
muted: false,
video_src: ''
video_src: '',
video_player_show: true,
}
},
created() {
@ -63,10 +64,19 @@
// #ifndef MP
const video = this.$refs.videoPlayer;
//
const src = JSON.parse(JSON.stringify(this.video_src));
let src = '';
if (!isEmpty(this.propSrc)) {
src = this.propSrc;
}
this.video_src = ''; //
//#ifdef H5
this.video_player_show = false;
//#endif
setTimeout(() => {
this.video_src = src; //
//#ifdef H5
this.video_player_show = true;
//#endif
// #ifdef APP-NVUE
video.load(); //
video.play().catch(() => this.retryLoadVideo());
@ -76,6 +86,7 @@
},
// ,
loadedmetadata() {
console.log('loadedmetadata');
this.$emit('loadedmetadata');
},
/**
@ -92,18 +103,23 @@
* @param {Object} e - 错误事件对象
*/
error(e) {
// #ifdef H5
// ,
if (e.type != 'otherError' || e.details != 'internalException') {
this.$emit('ended');
//
if (this.video_player_show) {
// #ifdef H5
// ,
if (e.type != 'otherError' || e.details != 'internalException') {
console.log('ended');
this.$emit('ended');
}
// #endif
// #ifdef APP-NVUE
if (!isEmpty(e.type) && e.type == 'error') {
this.$emit('ended');
}
// #endif
console.log(e, 'error');
}
// #endif
// #ifdef APP-NVUE
if (!isEmpty(e.type) && e.type == 'error') {
this.$emit('ended');
}
// #endif
console.log(e, 'error');
},
/**

View File

@ -27,7 +27,9 @@ export default {
lastLikeTime: 0, // 记录上次点赞时间,用于防抖
live_status: 1,
live_be_right_back_error: false,
load_timer: null, // 加载定时器
load_timer: null, // 延时显示视频的定时器
retry_count: 0 // 重试计数器
}
},
@ -128,38 +130,72 @@ export default {
},
/**
* 视频数据加载完成时触发
* 视频数据加载完成时触发
*/
loadedmetadata() {
// 如果加载完成了,延迟秒确定一下直播状态, 有的时候直播状态是正常的也加载成功了但是获取不到视频流需要确定一下没有执行error才算是真正的成功
// 如果加载完成了,延迟2秒确定一下直播状态, 有的时候直播状态是正常的也加载成功了但是获取不到视频流需要确定一下没有执行error才算是真正的成功
this.load_timer = setTimeout(() => {
this.retry_count = 0;
// 隐藏加载提示
uni.hideLoading();
// 直播状态为正常或者暂停直播了,才认为是正常的加载成功
if ([0, 1].includes(this.live_status)) {
// 如果重连的定时器还在运行中,则清除它
if (this.ended_timer) {
// 隐藏加载提示
clearTimeout(this.ended_timer);
}
this.live_be_right_back_error = false;
}
}, 300);
}, 2000);
},
/**
* 标记直播结束或者直播暂停
*/
ended() {
// 隐藏加载提示
uni.hideLoading();
uni.hideLoading();
// 如果加载定时器存在,则清除
if (this.load_timer) {
// 隐藏加载提示
clearTimeout(this.load_timer);
}
// 如果直播已结束,则返回
if (!this.is_live_ended) {
if (![1, 2].includes(this.live_status)) {
this.is_live_ended = true;
} else {
// 初始化重试计数器
if (this.retry_count === undefined) {
this.retry_count = 0;
}
// 如果历史定时器存在,则清除
if (this.ended_timer) {
// 隐藏加载提示
clearTimeout(this.ended_timer);
}
// 如果重试次数超过指定次数,则标记为真正结束
if (this.retry_count > 50) {
this.is_live_ended = true;
this.live_be_right_back_error = false;
// 重置计数器
this.retry_count = 0;
return;
}
// 增加重试计数
this.retry_count++;
// 暂停直播了或者继续直播了,则提示用户当前主播暂时离开
this.live_be_right_back_error = true;
// 延迟3秒后尝试重新连接
this.ended_timer = setTimeout(() => {
this.live_be_right_back_error = false;
}, 3000);
// 在定时结束后尝试重新连接
if (this.$refs.liveVideo) {
this.$refs.liveVideo.reload_video();
}
}, 5000);
}
}
},
@ -245,7 +281,7 @@ export default {
this.lastTapPosition = { x, y };
},
socket_live_status(status) {
this.live_status = status;
// this.live_status = status;
}
}
}

View File

@ -6,9 +6,19 @@
<full-screen-like-effect ref="fullScreenLikeEffect" :propCustomImages="like_show_imgs" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'"></full-screen-like-effect>
</view>
<template v-if="!is_loading">
<!-- 主播暂时离开的提示信息-->
<view v-if="live_be_right_back_error" class="live-pause flex-row align-c jc-c pointer-events-none">
<view class="flex-1 flex-col align-c jc-c">
<component-icon propName="smallbell" propSize="100rpx" propColor="#fff"></component-icon>
<text class="pointer-events-auto text-size mb-5 cr-white">主播暂时离开</text>
<text class="pointer-events-auto text-size-sm cr-white">休息片刻,更多精彩马上到来</text>
</view>
</view>
<!-- 主体内容显示 -->
<view class="live-content" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'">
<live-content ref="liveContent" :propWindowWidth="windowWidth" :propWindowHeight="windowHeight" :propLiveConfig="live_config" :propLiveShowImgs="like_show_imgs" @liveBack="live_back" @handleDoubleClick="handle_double_click" @handleTouchEnd="handle_touch_end" @liveStatus="socket_live_status"></live-content>
</view>
<!-- 直播间结束的显示 -->
<view v-if="is_live_ended" class="live-ended flex-row align-c jc-c" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'">
<view class="flex-col align-c">
<text class="live-ended-text">直播已结束</text>
@ -17,26 +27,24 @@
</button>
</view>
</view>
<!-- 主播暂时离开的提示信息-->
<view v-if="live_be_right_back_error" class="live-pause flex-row align-c jc-c pointer-events-none" :style="'width:' + windowWidth + 'px;'">
<view class="live-pause-tips pointer-events-auto">直播连接失败,正在尝试重新连接...</view>
</view>
</template>
</view>
</template>
<script>
import liveVideo from './components/video/video.vue';
import liveContent from './components/live-content/live-content.vue';
import componentIcon from './components/icon/icon.vue';
import componentLiveVideo from './components/video/video.vue';
import componentLiveContent from './components/live-content/live-content.vue';
// 引入点赞效果组件
import fullScreenLikeEffect from './components/full-screen-like-effect/full-screen-like-effect.vue';
import componentFullScreenLikeEffect from './components/full-screen-like-effect/full-screen-like-effect.vue';
// 引入混入公共逻辑避免nvue和vue使用同一套逻辑出现问题
import mixins from './mixins/mixins.js';
const app = getApp();
export default {
components: {
liveVideo,
liveContent,
fullScreenLikeEffect
componentIcon,
componentLiveVideo,
componentLiveContent,
componentFullScreenLikeEffect
},
mixins: [mixins],
data() {
@ -55,15 +63,7 @@
top: 0;
left: 0;
z-index: 9;
height: 600rpx;
background: transparent;
.live-pause-tips {
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
padding: 15rpx 20rpx;
font-size: 32rpx;
color: #fff;
}
background: linear-gradient(to bottom, #330066, #000000);
}
.live-content {
position: absolute;

View File

@ -1,13 +1,13 @@
<template>
<view :class="theme_view + ' re'">
<view class="pr live-bg" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="false">
<live-video v-if="!is_live_ended" ref="liveVideo" :propSrc="live_config.pull_flv_url || 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'" @ended="ended" @loadedmetadata="loadedmetadata" @mutedAutoPlaySuccess="muted_auto_play_success"></live-video>
<component-live-video v-if="!is_live_ended" ref="liveVideo" :propSrc="live_config.pull_flv_url || 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'" @ended="ended" @loadedmetadata="loadedmetadata" @mutedAutoPlaySuccess="muted_auto_play_success"></component-live-video>
<!-- 简化版点赞效果组件 -->
<full-screen-like-effect ref="fullScreenLikeEffect" :propCustomImages="like_show_imgs"></full-screen-like-effect>
<component-full-screen-like-effect ref="fullScreenLikeEffect" :propCustomImages="like_show_imgs"></component-full-screen-like-effect>
</view>
<template v-if="!is_loading">
<view class="live-content pointer-events-none">
<live-content ref="liveContent" :propWindowWidth="windowWidth" :propLiveConfig="live_config" :propLiveShowImgs="like_show_imgs" @liveBack="live_back" @liveStatus="socket_live_status"></live-content>
<component-live-content ref="liveContent" :propWindowWidth="windowWidth" :propLiveConfig="live_config" :propLiveShowImgs="like_show_imgs" @liveBack="live_back" @liveStatus="socket_live_status"></component-live-content>
</view>
<view v-if="is_live_ended" class="live-ended flex-row align-c jc-c">
<view class="flex-col align-c">
@ -25,24 +25,30 @@
</view>
<!-- 主播暂时离开的提示信息-->
<view v-if="live_be_right_back_error" class="live-pause flex-row align-c jc-c pointer-events-none">
<view class="live-pause-tips pointer-events-auto">主播暂时离开了, 请稍后...</view>
<view class="flex-1 flex-col align-c jc-c">
<component-icon propName="smallbell" propSize="100rpx" propColor="#fff"></component-icon>
<text class="pointer-events-auto text-size mt-5 cr-white">主播暂时离开</text>
<text class="pointer-events-auto text-size-sm mt-5 cr-white">休息片刻更多精彩马上到来</text>
</view>
</view>
</template>
</view>
</template>
<script>
import liveVideo from './components/video/video.vue';
import liveContent from './components/live-content/live-content.vue';
import componentIcon from './components/icon/icon.vue';
import componentLiveVideo from './components/video/video.vue';
import componentLiveContent from './components/live-content/live-content.vue';
//
import fullScreenLikeEffect from './components/full-screen-like-effect/full-screen-like-effect.vue';
import componentFullScreenLikeEffect from './components/full-screen-like-effect/full-screen-like-effect.vue';
// nvuevue使
import mixins from './mixins/mixins.js';
const app = getApp();
export default {
components: {
liveVideo,
liveContent,
fullScreenLikeEffect
componentLiveVideo,
componentLiveContent,
componentIcon,
componentFullScreenLikeEffect
},
mixins: [mixins],
data() {
@ -88,14 +94,7 @@
z-index: 8;
width: 100%;
height: 100%;
background: grey;
.live-pause-tips {
// background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
padding: 15rpx 20rpx;
font-size: 28rpx;
color: #fff;
}
background: linear-gradient(to bottom, #330066, #000000);
}
.live-muted {
position: absolute;