uni-app live-pusher 长时间黑屏
uni-app live-pusher 长时间黑屏
开发环境 | 版本号 | 项目创建方式 |
---|---|---|
Windows | 10 | HBuilderX |
产品分类:uniapp/App
PC开发环境操作系统:Windows
HBuilderX类型:正式
HBuilderX版本号:3.95
手机系统:Android
手机系统版本号:Android 9.0
手机机型:JUXING X21
页面类型:nvue
vue版本:vue2
打包方式:云端
项目创建方式:HBuilderX
示例代码:
<template>
<view class="pengke-camera" :style="{ width: windowWidth, height: windowHeight }">
<live-pusher id="livePusher" ref="livePusher" class="livePusher" url="" mode="SD" beauty="0" whiteness="0"
aspect="aspect" min-bitrate="200" audio-quality="16KHz" device-position="back" :auto-focus="true"
muted="true" :enable-camera="true" :enable-mic="false" :zoom="false" @statechange="statechange"
@netstatus="netstatus" @error="error" :style="{ width: windowWidth, height: windowHeight }"></live-pusher>
<view class="menu">
<!--返回键-->
<cover-image class="menu-back" :class="{'selected-btn':selectNum==0}"
src="/static/live-camera/back.png"></cover-image>
<!--快门键-->
<cover-image class="menu-snapshot" :class="{'selected-btn':selectNum==1}"
src="/static/live-camera/shutter.png"></cover-image>
<!--反转键-->
<cover-image class="menu-picture" :class="{'selected-btn':selectNum==2}"
src="/static/live-camera/picture.png"></cover-image>
</view>
</view>
<script>
let _this = null;
export default {
data() {
return {
eventTime: '',
poenCarmeInterval: null, //打开相机的轮询
aspect: '2:3', //比例
windowWidth: '', //屏幕可用宽度
windowHeight: '', //屏幕可用高度
camerastate: false, //相机准备好了
livePusher: null, //流视频对象
snapshotsrc: null, //快照
selectNum: 0
};
},
onLoad(e) {
_this = this;
this.initCamera();
},
onShow() {
this.listenEvent();
},
onHide() {
this.removeListener();
this.livePusher.stopPreview();
},
onReady() {
this.livePusher = uni.createLivePusherContext('livePusher', this);
var that = this;
setTimeout(function() {
that.startPreview(); //开启预览并设置摄像头
that.poenCarme();
}, 3000)
},
methods: {
listenEvent() {
var that = this;
// 监听键按下事件
uni.$on("keydown", function(res) {
switch (res.data) {
case 21:
if (that.selectNum > 0) {
that.selectNum = that.selectNum - 1;
} else {
that.selectNum = 2;
}
console.log("that.selectNum", that.selectNum)
break;
case 22:
if (that.selectNum < 2) {
that.selectNum = that.selectNum + 1;
} else {
that.selectNum = 0;
}
console.log("that.selectNum", that.selectNum)
break;
}
});
uni.$on("keyup", function(res) {
switch (res.data) {
case 139:
if (that.eventTime) {
var curTime = new Date() - that.eventTime
if (curTime < 500) {
that.eventTime = new Date();
return;
}
}
that.eventTime = new Date();
switch (that.selectNum) {
case 0:
uni.navigateBack();
break;
case 1:
that.snapshot();
break;
case 2:
that.picture();
break;
}
break;
}
});
// uni.$on("longpressed", function(res) {
// uni.navigateBack();
// });
},
removeListener() {
uni.$off('keydown');
uni.$off('keyup');
// uni.$off('longpressed');
},
//轮询打开
poenCarme() {
//#ifdef APP-PLUS
if (plus.os.name == 'Android') {
this.poenCarmeInterval = setInterval(function() {
// console.log("camerastate",_this.camerastate);
if (!_this.camerastate) {
// console.log("startPreview")
_this.startPreview();
}
}, 2500);
}
//#endif
},
//初始化相机
initCamera() {
uni.getSystemInfo({
success: function(res) {
_this.windowWidth = res.windowWidth;
_this.windowHeight = res.windowHeight;
let zcs = _this.aliquot(_this.windowWidth, _this.windowHeight);
_this.aspect = (_this.windowWidth / zcs) + ':' + (_this.windowHeight / zcs);
console.log('画面比例:' + _this.aspect);
}
});
},
//整除数计算
aliquot(x, y) {
if (x % y == 0) return y;
return this.aliquot(y, x % y);
},
//开始预览
startPreview() {
// console.log("preview",JSON.stringify(_this.livePusher))
this.livePusher.start({
success: a => {
console.log('livePusher.start:',JSON.stringify(a));
}
});
this.livePusher.startPreview({
success: (a) => {
// console.log(a)
},
fail: (e) => {
console.log(JSON.stringify(e) + "错误");
},
});
},
//停止预览
stopPreview() {
this.livePusher.stopPreview({
success: (a) => {
_this.camerastate = false;
}
});
},
//状态
statechange(e) {
plus.android.requestPermissions(['android.permission.CAMERA'], function(e) {
// console.log("requestPermissions", e);
})
const appAuthorizeSetting = uni.getAppAuthorizeSetting()
// console.log("cameraAuthorized", appAuthorizeSetting.cameraAuthorized)
//状态改变
console.log("statechange", e);
if (e.detail.code == 1007) {
_this.camerastate = true;
} else if (e.detail.code == -1301) {
_this.camerastate = false;
}
},
netstatus(e) {
console.log("netstatus", e);
},
error(e) {
console.log("error", e);
},
//返回
back() {
uni.navigateBack();
},
//抓拍
snapshot() {
//震动
uni.vibrateShort({
success: function() {
console.log('success');
}
});
//拍照
this.livePusher.snapshot({
success: (e) => {
console.log("--------step1--------")
_this.snapshotsrc = e.message.tempImagePath;
console.log(_this.snapshotsrc)
_this.stopPreview();
_this.setImage();
// uni.uploadFile({
// url: '上传接口的路径',
// filePath: e.path,
// name: 'imageFile',
// success: function(res) {
// //服务器返回的图片地址url
// },
// error: function(err) {
// console.log(err)
// }
// })
uni.navigateBack();
}
});
},
//反转
flip() {
this.livePusher.switchCamera();
},
//相册
picture() {
uni.navigateTo({
url: '/pages/picture/picture'
})
},
//设置
setImage() {
// let pages = getCurrentPages();
// let prevPage = pages[pages.length - 2];
// prevPage.$vm.setImage({
// path: _this.snapshotsrc
// });
}
}
};
</script>
.pengke-camera {
height: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background-color: #000000;
.livePusher {
height: 95%;
width: 200rpx;
}
.menu {
width: 100rpx;
height: 750rpx;
position: absolute;
right: 10rpx;
z-index: 99;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
// background-color: #00aaff;
background-image: url(/static/live-camera/bar.png);
.selected-btn {
border-style: solid;
border-width: 5px;
border-color: #00ffff;
}
.menu-mask {
width: 180rpx;
height: 750rpx;
}
.menu-back {
margin-top: 10rpx;
margin-bottom: 10rpx;
width: 80rpx;
height: 80rpx;
align-items: center;
justify-content: center;
}
.menu-snapshot {
margin-top: 10rpx;
margin-bottom: 10rpx;
width: 80rpx;
height: 80rpx;
}
.menu-picture {
margin-top: 10rpx;
margin-bottom: 10rpx;
width: 80rpx;
height: 80rpx;
align-items: center;
justify-content: center;
}
}
}
操作步骤:
每次跳转到这个页面就会等很久差不多2~3分钟才能获取到摄像头的视频流,黑屏期间一直上报
{
"type": "statechange",
"timeStamp": 1698976851606,
"target": {
"id": "livePusher",
"dataset": {},
"offsetLeft": 0,
"offsetTop": 0
},
"currentTarget": {
"id": "livePusher",
"dataset": {},
"offsetLeft": 0,
"offsetTop": 0
},
"detail": {
"message": "打开摄像头失败,请确认摄像头权限是否打开",
"code": -1301
},
"stopPropagation": "function() { [native code] }"
}
预期结果:
跳转到此页面后live-pusher能够短时间内获取到摄像头的视频流
实际结果:
长时间黑屏
bug描述:
我的需求是通过live-pusher实现自定义相机的功能,按照官方文档的推荐使用的nvue写的页面,在我的Android 9.0的系统设备上运行的软件,live-pusher的statechange返回事件一直上报:“打开摄像头失败,请确认摄像头权限是否打开“,错误码-1301,我查看设备摄像头权限处于打开的,使用uni.chooseImage来调用相机是正常的,但live-pusher总是长时间黑屏,需要放很久才能显示正常,官方的demo也是一样的
更多关于uni-app live-pusher 长时间黑屏的实战教程也可以访问 https://www.itying.com/category-93-b0.html
我使用 live-pusher 切换到后台再返回就是黑屏呢
在 uni-app 中使用 live-pusher
组件时,如果出现长时间黑屏的问题,可能是由多种原因引起的。以下是一些常见的原因及解决方法:
1. 权限问题
- 原因:应用没有获取摄像头或麦克风的权限。
- 解决方法:
- 确保在
manifest.json
中正确配置了权限:"permission": { "scope.camera": { "desc": "需要访问摄像头进行直播" }, "scope.record": { "desc": "需要访问麦克风进行直播" } }
- 在代码中动态请求权限:
uni.authorize({ scope: 'scope.camera', success() { console.log('摄像头权限已授权'); }, fail() { console.log('摄像头权限未授权'); } });
- 确保在
2. 摄像头未正确初始化
- 原因:摄像头可能未正确初始化或未绑定到
live-pusher
组件。 - 解决方法:
- 确保
live-pusher
组件的camera
属性设置为front
或back
:<live-pusher camera="front"></live-pusher>
- 检查设备是否支持摄像头功能。
- 确保
3. 推流地址错误
- 原因:推流地址(
url
)无效或格式错误。 - 解决方法:
- 确保推流地址正确,并且符合 RTMP 协议格式。
- 测试推流地址是否可用。
4. 网络问题
- 原因:网络不稳定或无法连接到推流服务器。
- 解决方法:
- 检查设备的网络连接是否正常。
- 尝试切换到更稳定的网络环境。
5. 组件生命周期问题
- 原因:
live-pusher
组件可能未在正确的生命周期中初始化或销毁。 - 解决方法:
- 确保在
onReady
或onLoad
生命周期中初始化live-pusher
。 - 在页面销毁时调用
stop
方法:onUnload() { this.livePusherContext.stop(); }
- 确保在
6. 设备兼容性问题
- 原因:某些设备可能存在兼容性问题。
- 解决方法:
- 测试不同设备,确认是否为特定设备问题。
- 更新设备系统或 uni-app SDK 版本。
7. 代码逻辑问题
- 原因:代码中可能存在逻辑错误,导致
live-pusher
未正确启动。 - 解决方法:
- 检查代码逻辑,确保
start
方法被正确调用:this.livePusherContext.start();
- 添加错误监听,捕获异常:
this.livePusherContext.on('error', (err) => { console.error('推流错误:', err); });
- 检查代码逻辑,确保