- 发布:2020-05-25 09:59
- 更新:2020-07-08 10:41
- 阅读:2402
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: win10
HBuilderX类型: 正式
HBuilderX版本号: 2.7.5
手机系统: 全部
手机厂商: 华为
页面类型: nvue
打包方式: 云端
项目创建方式: HBuilderX
测试过的手机:
操作步骤:
//推流页面
<template>
<view class="all">
<view class="video" @click="clagFalg()">
<live-pusher :style="[{width: widthWin + 'px',height:heightWin + 'px'}]" id='livePusher' ref="livePusher" class="livePusher"
:url="url" mode="FHD" @statechange="statechange" aspect="9:16" :beauty="index" :whiteness="indexOne" @error="error"></live-pusher>
</view>
<!-- 下方按钮 -->
<view class="item" :style="{width:widthWin}">
<!-- 切换摄像头-->
<view class="item-image" @click='switchCamera'>
<image src="../../static/video/camara.png" mode="aspectFit" class="item-stop"></image>
</view>
<!-- 美颜 -->
<view class="item-image" >
<image src="../../static/video/yan.png" mode="aspectFit" class="item-stop"></image>
</view>
<!-- 录制按钮 -->
<view class="item-image" @click="changeshow">
<image :src="img" mode="aspectFit" class="item-stop"></image>
</view>
<!-- bianji -->
<view class="item-image" @click='isShowMessage = true'>
<image src="../../static/video/edit.png" mode="aspectFit" class="item-stop"></image>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
url: '',
widthWin: '', //页面宽度
heightWin: '', //页面宽度
context: null,
isShow: true, //直播是否开启的状态
img: '../../static/video/stop.png', //开始,暂停图标
pauseFale: false, //判断是否是暂停状态
startFale: false, //判断是否是播放状态
},
created() {
var buby = uni.getSystemInfoSync()
this.widthWin = buby.windowWidth
this.heightWin = buby.windowHeight
},
onLoad(option) {
const value = JSON.parse(decodeURIComponent(option.data))
this.url = value.pushUrl
},
mounted() {
// 初始化直播推流
this.context = uni.createLivePusherContext('livePusher', this)
this.startPreview() //开启摄像头预览
},
onShow() {
//如果是暂停状态恢复推流
if (this.pauseFale) {
this.context.resume({
success: (e) => {
},
fail: (e) => {
c
}
});
}
},
onHide() {
//如果是播放状态隐藏页面暂停推流
if (this.startFale) {
this.pause()
}
},
methods: {
// 切换状态,是开始推流还是停止推流
changeshow() {
this.isShow = !this.isShow
if (this.isShow) {
uni.showModal({
title: '提示',
content: '确定要退出直播吗',
success: res => {
if (res.confirm) {
this.stop()
} else if (res.cancel) {
}
}
});
} else {
this.img = '../../static/video/start.png'
this.start()
}
},
statechange(e) {
// console.log("statechange:" + JSON.stringify(e));
},
error(e) {
console.log("error:" + JSON.stringify(e));
},
start: function() {
this.context.start({
success: (a) => {
console.log("livePusher.start:" + JSON.stringify(a));
this.startFale = true
},
fail: (e) => {
// console.log('StartError' + JSON.stringify(e));
}
});
},
pause: function() {
this.context.pause({
success: (a) => {
console.log("livePusher.pause:" + JSON.stringify(a));
this.pauseFale = true
}
});
},
stop: function() {
this.context.stop({
success: (a) => {
console.log(JSON.stringify(a));
}
});
},
//切换前后摄像头
switchCamera: function() {
this.context.switchCamera({
success: (a) => {
console.log("livePusher.switchCamera:" + JSON.stringify(a));
}
});
},
//开启摄像头预览
startPreview: function() {
this.context.startPreview({
success: (a) => {
// console.log("livePusher.startPreview:" + JSON.stringify(a));
}
});
},
//关闭摄像头预览
stopPreview: function() {
this.context.stopPreview({
success: (a) => {
console.log("livePusher.stopPreview:" + JSON.stringify(a));
}
});
},
//渲染错误事件
error: function() {
console.log("error:" + JSON.stringify(e));
}
}
}
</script>
//播放页面
<template>
<view class="video" :style="[{width: widthWin + 'px',height:heightWin + 'px'}]">
<video :style="[{width: widthWin + 'px',height:heightWin + 'px'}]" id="myVideo" class="videosty" :src="livePlay"
:autoplay="true" :enable-progress-gesture="false" object-fit="fill" :controls="false"
:enable-play-gesture="false" :vslide-gesture-in-fullscreen="false" @timeupdate="timeupdate" @error="videoErrorCallback" @waiting='waiting' @ended="ended" @play='start' @pause="stop" >
</video>
</view>
</template>
<script>
export default {
data() {
return {
widthWin: '', //页面宽度
heightWin: '', //页面宽度
livePlay: '', //播放地址
}
},
onLoad(option) {
const value = JSON.parse(decodeURIComponent(option.data))
this.livePlay = value.pullUrl
var buby = uni.getSystemInfoSync()
this.widthWin = buby.windowWidth
this.heightWin = buby.windowHeight
},
methods: {
//开始播放
play() {
this.videoContext.play()
},
//暂停播放
pause() {
this.videoContext.pause()
},
//监听播放状态
start() {
console.log('开始播放')
},
//视频出现缓冲时触发
waiting(e){
console.log('wait' + e);
},
//当播放到末尾时触发 ended 事件
ended(e){
console.log('ended' + e);
},
//当播放停时触发
stop() {
console.log('停止播放')
},
//视频播放出错时触发
videoErrorCallback(e) {
console.log('err' + e);
},
//播放进度变化时触发
timeupdate(e){
console.log('err' + JSON.stringify(e));
}
}
}
</script>
//推流页面
<template>
<view class="all">
<view class="video" @click="clagFalg()">
<live-pusher :style="[{width: widthWin + 'px',height:heightWin + 'px'}]" id='livePusher' ref="livePusher" class="livePusher"
:url="url" mode="FHD" @statechange="statechange" aspect="9:16" :beauty="index" :whiteness="indexOne" @error="error"></live-pusher>
</view>
<!-- 下方按钮 -->
<view class="item" :style="{width:widthWin}">
<!-- 切换摄像头-->
<view class="item-image" @click='switchCamera'>
<image src="../../static/video/camara.png" mode="aspectFit" class="item-stop"></image>
</view>
<!-- 美颜 -->
<view class="item-image" >
<image src="../../static/video/yan.png" mode="aspectFit" class="item-stop"></image>
</view>
<!-- 录制按钮 -->
<view class="item-image" @click="changeshow">
<image :src="img" mode="aspectFit" class="item-stop"></image>
</view>
<!-- bianji -->
<view class="item-image" @click='isShowMessage = true'>
<image src="../../static/video/edit.png" mode="aspectFit" class="item-stop"></image>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
url: '',
widthWin: '', //页面宽度
heightWin: '', //页面宽度
context: null,
isShow: true, //直播是否开启的状态
img: '../../static/video/stop.png', //开始,暂停图标
pauseFale: false, //判断是否是暂停状态
startFale: false, //判断是否是播放状态
},
created() {
var buby = uni.getSystemInfoSync()
this.widthWin = buby.windowWidth
this.heightWin = buby.windowHeight
},
onLoad(option) {
const value = JSON.parse(decodeURIComponent(option.data))
this.url = value.pushUrl
},
mounted() {
// 初始化直播推流
this.context = uni.createLivePusherContext('livePusher', this)
this.startPreview() //开启摄像头预览
},
onShow() {
//如果是暂停状态恢复推流
if (this.pauseFale) {
this.context.resume({
success: (e) => {
},
fail: (e) => {
c
}
});
}
},
onHide() {
//如果是播放状态隐藏页面暂停推流
if (this.startFale) {
this.pause()
}
},
methods: {
// 切换状态,是开始推流还是停止推流
changeshow() {
this.isShow = !this.isShow
if (this.isShow) {
uni.showModal({
title: '提示',
content: '确定要退出直播吗',
success: res => {
if (res.confirm) {
this.stop()
} else if (res.cancel) {
}
}
});
} else {
this.img = '../../static/video/start.png'
this.start()
}
},
statechange(e) {
// console.log("statechange:" + JSON.stringify(e));
},
error(e) {
console.log("error:" + JSON.stringify(e));
},
start: function() {
this.context.start({
success: (a) => {
console.log("livePusher.start:" + JSON.stringify(a));
this.startFale = true
},
fail: (e) => {
// console.log('StartError' + JSON.stringify(e));
}
});
},
pause: function() {
this.context.pause({
success: (a) => {
console.log("livePusher.pause:" + JSON.stringify(a));
this.pauseFale = true
}
});
},
stop: function() {
this.context.stop({
success: (a) => {
console.log(JSON.stringify(a));
}
});
},
//切换前后摄像头
switchCamera: function() {
this.context.switchCamera({
success: (a) => {
console.log("livePusher.switchCamera:" + JSON.stringify(a));
}
});
},
//开启摄像头预览
startPreview: function() {
this.context.startPreview({
success: (a) => {
// console.log("livePusher.startPreview:" + JSON.stringify(a));
}
});
},
//关闭摄像头预览
stopPreview: function() {
this.context.stopPreview({
success: (a) => {
console.log("livePusher.stopPreview:" + JSON.stringify(a));
}
});
},
//渲染错误事件
error: function() {
console.log("error:" + JSON.stringify(e));
}
}
}
</script>
//播放页面
<template>
<view class="video" :style="[{width: widthWin + 'px',height:heightWin + 'px'}]">
<video :style="[{width: widthWin + 'px',height:heightWin + 'px'}]" id="myVideo" class="videosty" :src="livePlay"
:autoplay="true" :enable-progress-gesture="false" object-fit="fill" :controls="false"
:enable-play-gesture="false" :vslide-gesture-in-fullscreen="false" @timeupdate="timeupdate" @error="videoErrorCallback" @waiting='waiting' @ended="ended" @play='start' @pause="stop" >
</video>
</view>
</template>
<script>
export default {
data() {
return {
widthWin: '', //页面宽度
heightWin: '', //页面宽度
livePlay: '', //播放地址
}
},
onLoad(option) {
const value = JSON.parse(decodeURIComponent(option.data))
this.livePlay = value.pullUrl
var buby = uni.getSystemInfoSync()
this.widthWin = buby.windowWidth
this.heightWin = buby.windowHeight
},
methods: {
//开始播放
play() {
this.videoContext.play()
},
//暂停播放
pause() {
this.videoContext.pause()
},
//监听播放状态
start() {
console.log('开始播放')
},
//视频出现缓冲时触发
waiting(e){
console.log('wait' + e);
},
//当播放到末尾时触发 ended 事件
ended(e){
console.log('ended' + e);
},
//当播放停时触发
stop() {
console.log('停止播放')
},
//视频播放出错时触发
videoErrorCallback(e) {
console.log('err' + e);
},
//播放进度变化时触发
timeupdate(e){
console.log('err' + JSON.stringify(e));
}
}
}
</script>
预期结果:
当live-pusher暂停推流时,video 标签会有一个可以判断暂停推流的回调
当live-pusher暂停推流时,video 标签会有一个可以判断暂停推流的回调
实际结果:
而且当live-pusher暂停推流时,video 标签的这些方法@timeupdate @error @waiting @ended @pla @pause 都没有可以判断暂停推流的反应,而且@timeupdate 进度也依旧正常加载
而且当live-pusher暂停推流时,video 标签的这些方法@timeupdate @error @waiting @ended @pla @pause 都没有可以判断暂停推流的反应,而且@timeupdate 进度也依旧正常加载
bug描述:
做APP端直播功能
推流页面使用的是live-pusher标签,拉流播放页面使用的是video标签,当live-pusher暂停推流时,video播放黑屏,live-pusher暂停推流多长时间,video标签就黑屏多长时间, 这样就很不美观了。
想实现的功能是主播离开推流页面,就暂停推流,主播暂停推流时,播放页面显示一个“主播不在,请稍等的标语”。
但是video怎么能检测到推流暂停了呢?
而且当live-pusher暂停、播放黑屏时,video 标签的这些方法@timeupdate @error @waiting @ended @pla @pause 都没有反应,而且@timeupdate 进度也依旧正常加载
3 个回复
7***@qq.com
同求,我们也正在做直播,遇到这个问题了
6***@qq.com
同求啊~~
karlar - 一只程序猿
问题解决了,需要和后台配合,在推流页面里,暂停推流时,请求一个接口,向后台发送请求,后台就会停止推流。这时拉流组件的@error的方法就会触发,这个时候我们就可以在@error触发的方法做下一步操作。
karlar
同样恢复推流的时候也想=向后台发送一个请求,后台就会继续推流,请求成功后,发送一个监听,拉流页面监听成功后再做后续操作
2020-07-08 10:44
8***@qq.com
你好,请问你用的拉流组件是video吗
2020-07-23 13:20
karlar
回复 8***@qq.com: 是的
2020-07-24 09:13
专属草根
回复 karlar: 你好,请问一下,这个主播如果恢复推流,video怎样才能检测到呢?
2020-12-19 10:26
karlar
回复 专属草根: 如果暂停推流的话,video会报错,这个时候我用v-if控制video的节点的存在,每隔一段时间就让video节点重新显示再加载一遍,如果恢复推的话,video就会恢复播放。否则的话video就会报错,然后v-if判断。 只能想到这个笨方法了
2020-12-19 12:05