微信小程序录制视频方法踩坑总结

**

工作中需要微信小程序实现录制15s视频上传,部分用户反馈无法录制视频的问题,所以在此总结一下经验

**
下面这张图片这是问题的表现,部分机型用户松开拍摄时提示未完成拍摄,导致无法上传视频。
在这里插入图片描述
上面的问题是使用

wx.chooseVideo({
  sourceType: ['camera'],
  maxDuration: 60,
  camera: 'back',
  success(res) {
    console.log(res.tempFilePath)
  }
})

wx.chooseVideo是微信官方提供的接口,不需要用户授权,可直接调用返回拍摄完的视频地址,但是部分机型使用该接口时会出现上述问题,导致无法完成拍摄。

解决方法:
使用wx.createCameraContext(),自己定义录制方法。
注意点:
1.使用该方法需要用户授权摄像头权限和麦克风权限,需要对未授权时的情况进行处理
2.startRecord和stopRecord方法注意调用时机,都不可连续调用,需要对用户连续点击的行为做处理

代码如下:

index.wxml

<view class="video">
	<video wx:if="{{video}}" src="{{video}}" style="width: 100%;display: block;"></video>
	<button type="primary" bindtap="checkSetting">录制视频demo</button>
</view>

index.js

const app = getApp()
Page({
	data: {
		video:null
	},
	onLoad: function(options) {
		
	},
	onShow() {
		/**
		 * 每次进入页面判断本地是否存在录制视频地址,有则取,取完清除
		 */
		if (wx.getStorageSync('auth_video')) {
			this.setData({
				video: wx.getStorageSync('auth_video')
			})
			wx.removeStorageSync('auth_video')
		}
	},
	/**
	 * 由于录像页面使用了camera标签,使用该标签时需要获取摄像头权限,否则无法捕捉画面
	 * 所以每次进入页面时先进行检验用户是否授权摄像头权限
	 */
	checkSetting() {
		wx.getSetting({
			success: (res) => {
				console.log(res)
				let authSetting = res.authSetting
				/**
				 * authSetting.hasOwnProperty('scope.camera')==true 说明用户不是首次授权
				 * authSetting['scope.camera']==false 说明用户未允许授权
				 * 只有当两个条件同时满足时需要提示用户开启授权
				 */
				if (authSetting.hasOwnProperty('scope.camera') && !authSetting['scope.camera']) {
					wx.showModal({
						content: '检测到您当前未开启摄像头权限,将无法使用相机功能',
						confirmText: '去开启',
						success: (res) => {
							if (res.confirm) {
								console.log('用户点击确定')
								wx.openSetting({
									success(res) {
										console.log(res.authSetting)
									}
								});
							} else if (res.cancel) {
								console.log('用户点击取消')
							}
						}
					})
				} else {
					wx.navigateTo({
						url:"../camera/camera"
					})
				}
			}
		})
	}
})

camera.wxml

<view class="video">
	<view wx:if="{{!video_url}}" style="position: relative;">
		<cover-view class="time-container" wx:if="{{isRecording}}">
			<cover-view class="time">正在录制 {{time}}s</cover-view>
		</cover-view>
		<cover-view class="change-btn" wx:else bindtap="changePosition">
			<cover-view>点击切换{{devicePosition=='front'?'后置':'前置'}}摄像头</cover-view>
		</cover-view>
		<camera binderror="getError" device-position="{{devicePosition}}" style="width: 100vw;height: 100vh;"></camera>
		<cover-view class="btn-container">
			<cover-view class="btn-item" bindtap="back" style="background-color: #ddd;">返回</cover-view>
			<cover-view class="btn-item" bindtap="record">{{isRecording?'结束录制':'点击录制'}}</cover-view>
		</cover-view>
	</view>
	<view wx:else style="position: fixed;width: 100vw;height: 100vh;">
		<video src="{{video_url}}" style="width: 100%;height: 100%;" autoplay="{{true}}" loop="{{true}}" controls="{{false}}"></video>
		<cover-view class="btn-container">
			<cover-view class="btn-item" bindtap="recordAgain">重新录制</cover-view>
			<cover-view class="btn-item" bindtap="sureVideo">确认选择</cover-view>
		</cover-view>
	</view>
</view>

camera.wxss


.time-container{
	position: absolute;
	width: 100%;
	left:0;
	top: 0;
	height: 240rpx;
	display: flex;
	justify-content: center;
	align-items: center;
	background-color: rgba(0,0,0,0.4);
	z-index: 100;
}
.change-btn{
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
	display: flex;
	align-items: center;
	height: 100rpx;
	color: #fff;
	font-size: 30rpx;
	padding: 0 50rpx;
	border-radius: 50rpx;
	z-index: 100;
	background-color: rgba(0,0,0,0.5);
}
.time{
	font-size: 30rpx;
	color: red;
	padding: 0 20rpx;
	margin-top: 30rpx;
}
.btn-container{
	position: absolute;
	width: 100%;
	padding: 0 80rpx;
	box-sizing: border-box;
	bottom: 160rpx;
	display: flex;
	justify-content: space-between;
	z-index: 100;
}
.btn-item{
	padding: 30rpx 0;
	border-radius: 45rpx;
	background-color: #FF6685;
	color: #fff;
	font-size: 32rpx;
	text-align: center;
	width: 240rpx;
}

camera.js

const app = getApp()
Page({
	data: {
		ctx: null,
		isRecording: false,
		video_url: null,
		time: 0,
		min_time:5,	//录制视频最小时长
		timer: null,
		devicePosition: "back", //摄像头朝向
		isStart:false, //记录用户点击开始录制的状态
		isStop:false //记录用户点击结束录制的状态
	},
	onLoad(options) {
		const ctx = wx.createCameraContext()
		this.setData({
			ctx
		})
	},
	onUnload() {
		clearInterval(this.data.timer)
	},
	//切换前置/后置摄像头
	changePosition() {
		this.setData({
			devicePosition: this.data.devicePosition == 'back' ? 'front' : 'back'
		})
	},
	checkSetting() {
		//这里定义一个状态isStart来记录用户点击开始录制行为,待startRecord接口请求成功后还原状态
		if(this.data.isStart){
			return
		}
		this.data.isStart = true
		/**
		 * 调用wx.createCameraContext().startRecord()方法需要获取用户麦克风权限,否则无法调用且无法录制视频
		 * 所以每次进入页面时先进行检验用户是否授权麦克风权限
		 */
		wx.getSetting({
			success: (res) => {
				console.log(res)
				let authSetting = res.authSetting
				/**
				 * 原理同检测摄像头权限
				 */
				if (authSetting.hasOwnProperty('scope.record') && !authSetting['scope.record']) {
					wx.showModal({
						content: '检测到您当前未开启麦克风权限,将无法录制视频',
						confirmText: '去开启',
						success: (res) => {
							if (res.confirm) {
								console.log('用户点击确定')
								wx.openSetting({
									success(res) {
										console.log(res.authSetting)
									}
								});
							} else if (res.cancel) {
								console.log('用户点击取消')
								// this.back()
							}
						}
					})
				} else {
					this.startRecord()
				}
			}
		})
	},
	//用户进入页面授权时点击不允许授权时触发该方法,且不允许授权后每次进入页面都会直接触发
	getError() {
		console.log("用户未授权使用摄像头")
		this.back()
	},
	//点击开始录制/结束录制
	record() {
		if (this.data.isRecording) {
			console.log("结束录制视频")
			this.stopRecord()
		} else {
			console.log("开始录制视频")
			this.checkSetting()
		}
	},
	//开始录制
	startRecord() {
		this.data.ctx.startRecord({
			timeoutCallback: (res) => {
				/**
				 * 微信官方限制
				 * 使用该方法录制视频最多录制30s,30s后自动停止录制
				 * 停止录制计时
				 */
				console.log("30秒时间结束,自动停止录制")
				console.log(res)
				clearInterval(this.data.timer)
				this.setData({
					video_url: res.tempVideoPath,
					isRecording: false
				})
			},
			success: (res) => {
				console.log(res)
				this.timing()
				this.setData({
					isRecording: true
				})
				this.data.isStart = false
			},
			fail:(err)=>{
				console.log(err)
				this.data.isStart = false
			}
		})
	},
	//结束录制
	stopRecord() {
		//stopRecord方法不可连续调用,否则无法停止录制
		//这里定义一个状态isStop来记录用户点击结束录制行为,待stopRecord接口请求成功后还原状态
		if(this.data.isStop){
			return
		}
		if(this.data.time<this.data.min_time){
			wx.showToast({
				title:"视频时长小于"+this.data.min_time+"秒",
				icon:"none"
			})
			return
		}
		wx.showLoading({
			title:"请稍候"
		})
		this.data.isStop = true
		this.data.ctx.stopRecord({
			//compressed: false,  //是否压缩录完的视频
			success: (res) => {
				console.log(res)
				clearInterval(this.data.timer)
				this.setData({
					video_url: res.tempVideoPath,
					isRecording: false
				})
				this.data.isStop = false
				wx.hideLoading()
			},
			fail(err){
				console.log(err)
				this.data.isStop = false
				wx.hideLoading()
			}
		})
	},
	//计时
	timing() {
		let time = 0
		//每次计时前先将页面上的时间重置为0
		this.setData({
			time
		})
		let self = this
		let timer = setInterval(function() {
			time++
			console.log(time)
			self.setData({
				time
			})
		}, 1000)
		this.setData({
			timer
		})
	},
	//重新录制
	recordAgain() {
		this.setData({
			video_url: null
		})
	},
	//返回上一页
	back() {
		wx.navigateBack()
	},
	//确认选择
	sureVideo() {
		/**
		 * 将录完的视频地址保存本地,返回上一页时在onShow里面判断本地是否存在录制视频的地址
		 */
		wx.setStorageSync('auth_video', this.data.video_url)
		wx.navigateBack()
	}
})

效果图:

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值