uniapp app录音插件

uniapp yekong

插件地址

插件地址

可能遇到问题 uni-app 打包成安卓应用后 长按录音@touchend 不执行
插件二次修改,因为涉及到权限问题,所以在源插件的基础上增加了权限的判断。使用到的permission.js在这里查看

插件二次修改

<template>
	<div>
		<div @click="open">
			<slot></slot>
		</div>
		<u-popup :show="show" @close="close" @open="open">
			<view class="recorder">
				<view class="re-top" v-if="showTop">
					<view class="re-cancel" @click="cancel">取消</view>
					<view class="re-confirm" :style="{color: theme}" @click="confirm">{{ confirmText }}</view>
				</view>
				<text class="title">{{ finish ? '点击播放' : '长按录制语音' }}</text>
				<view class="recorder-box" v-if="!finish" @click="handle" @longpress="onStartRecoder"
					@touchend="onEndRecoder">
					<u-circle-progress2 :active-color="theme" :duration="0" :percent="calcProgress">
						<view class="u-progress-content">
							<image src="/static/sound-recording/voice.png" mode="aspectFit" :style="{
	          width: width,
	          height: height
	        }"></image>
						</view>
					</u-circle-progress2>
				</view>
				<view class="recorder-box" v-else @click="playVoice">
					<u-circle-progress2 :active-color="theme" :duration="0" :percent="playProgress">
						<view class="u-progress-content">
							<image src="/static/sound-recording/play.png" mode="aspectFit" :style="{
	          width: width,
	          height: height
	        }" v-if="!playStatus"></image>
							<image src="/static/sound-recording/pause.png" mode="aspectFit" :style="{
	          width: width,
	          height: height
	        }" v-else></image>
						</view>
					</u-circle-progress2>
				</view>
				<text class="now-date">{{ reDate }}</text>
				<view @click="reset">重新录制</view>
			</view>
		</u-popup>
	</div>
</template>

<script>
	const recorderManager = uni.getRecorderManager();
	const innerAudioContext = uni.createInnerAudioContext();
	import permision from "@/utils/permission.js"
	export default {
		components: {},
		props: {
			width: {
				type: String,
				default: '60rpx'
			},
			height: {
				type: String,
				default: '60rpx'
			},
			showTop: {
				type: Boolean,
				default: true
			},
			maximum: {
				type: [Number, String],
				default: 15
			},
			duration: {
				type: Number,
				default: 20
			},
			theme: {
				type: String,
				default: '#32b99d'
			},
			confirmText: {
				type: String,
				default: '完成'
			}
		},
		data() {
			return {
				reDate: '00:00',
				sec: 0,
				min: 0,
				finish: false,
				voicePath: '',
				playProgress: 100,
				playTimer: null,
				timer: null,
				playStatus: false,
				show: false
			};
		},
		created() {
			// 监听
			this.onMonitorEvents()
		},
		computed: {
			// 录制时间计算
			calcProgress() {
				return (this.sec + (this.min * 60)) / this.maximum * 100
			}
		},
		methods: {
			open() {
				let env = uni.getSystemInfoSync().platform
				if (env === 'android') {
					permision.requestAndroidPermission('android.permission.RECORD_AUDIO').then((e) => {
						if (e === -1) {
							uni.showToast({
								title: '您已经永久拒绝录音权限,请在应用设置中手动打开',
								icon: 'none',
							})
						} else if (e === 0) {
							uni.showToast({
								title: '您拒绝了录音授权',
								icon: 'none',
							})
						} else if (e === 1) {
							this.show = true
						} else {
							uni.showToast({
								title: '授权返回值错误',
								icon: 'none',
							})
						}
					}).catch((err) => {
						uni.showToast({
							title: '拉起录音授权失败',
							icon: 'none',
						})
					})
				} else if (env === 'ios') {
					if (permision.judgeIosPermission("record"))
						this.show = true
					else
						uni.showToast({
							title: '您拒绝了录音授权,请在应用设置中手动打开',
							icon: 'none',
						})
				}
			},
			close() {
				this.show = false
			},
			// 完成事件
			confirm() {
				if (!innerAudioContext.paused) {
					innerAudioContext.stop()
				}
				this.$emit('confirm', this.voicePath)
				this.close()
			},
			// 取消事件
			cancel() {
				if (!innerAudioContext.paused) {
					innerAudioContext.stop()
				}
				this.$emit('cancel')
				this.close()
			},
			// 点击事件
			handle() {
				this.$emit('click')
			},
			// 重新录制
			reset() {
				this.voicePath = ''
				this.min = 0
				this.sec = 0
				this.reDate = '00:00'
				this.playProgress = 100
				this.finish = false
				this.$emit('reset')
			},
			// 播放暂停录音
			playVoice() {
				innerAudioContext.src = this.voicePath;

				if (innerAudioContext.paused) {
					innerAudioContext.play()
					this.playStatus = true
				} else {
					innerAudioContext.stop();
				}
				this.$emit('playVoice', innerAudioContext.paused)
			},
			// 录制结束
			onEndRecoder() {
				recorderManager.stop()
			},
			// 开始录制
			onStartRecoder() {
				recorderManager.start({
					duration: this.maximum * 1000
				})
			},
			// 监听
			onMonitorEvents() {
				// 录制开始
				recorderManager.onStart(() => {
					// uni.showLoading({
					// 	title: '录制中...',
					// 	mask: false
					// })
					this.startDate()
					this.$emit('start')
				})
				// 录制结束
				recorderManager.onStop(({
					tempFilePath
				}) => {
					this.voicePath = tempFilePath
					clearInterval(this.timer)
					uni.hideLoading()
					this.finish = true
					this.$emit('end')
				})
				// 播放进度
				innerAudioContext.onTimeUpdate(() => {
					let totalDate = innerAudioContext.duration
					let nowTime = innerAudioContext.currentTime
					let surplus = totalDate - nowTime
					this.playProgress = surplus / totalDate * 100

					let _min = Math.floor(surplus / 60)
					if (_min < 10) _min = '0' + _min;
					let _sec = Math.floor(surplus % 60)
					if (_sec < 10) _sec = '0' + _sec;
					this.reDate = _min + ':' + _sec
				})
				// 播放暂停
				innerAudioContext.onPause(() => {
					this.resetDate()
					this.playProgress = 100
					this.playStatus = false
					console.log('播放暂停')
					this.$emit('stop')
				})
				// 播放停止
				innerAudioContext.onStop(() => {
					this.resetDate()
					this.playProgress = 100
					this.playStatus = false
					console.log('播放停止')
					this.$emit('stop')
				})
			},
			// 录音计时
			startDate() {
				clearInterval(this.timer)
				this.sec = 0
				this.min = 0
				this.timer = setInterval(() => {
					this.sec += this.duration / 1000
					if (this.sec >= 60) {
						this.min++
						this.sec = 0
					}
					this.resetDate()
				}, this.duration)
			},
			// 播放时间
			resetDate() {
				let _s = this.sec < 10 ? '0' + parseInt(this.sec) : parseInt(this.sec)
				let _m = this.min < 10 ? '0' + this.min : this.min
				this.reDate = _m + ':' + _s
			}
		}
	}
</script>

<style lang="scss">
	.recorder {
		position: relative;
		display: flex;
		align-items: center;
		flex-direction: column;
		background-color: #fff;
		font-size: 24rpx;
		width: 100%;
		padding-bottom: 30rpx;

		.re-top {
			display: flex;
			justify-content: space-between;
			padding: 10rpx 20rpx;
			width: 100%;
			font-size: 28rpx;
			box-sizing: border-box;
		}

		.title {
			font-size: 36rpx;
			color: #333;
			padding: 20rpx 0 30rpx;
		}

		.recorder-box {
			position: relative;
		}

		.now-date {
			font-size: 28rpx;
			color: #666;
			padding: 20rpx 0;
		}
	}
</style>

插件使用

<sound-recording @confirm="getRecording">
					<u-cell title="录音" :isLink="true" value="开始录音">
						<view slot="value">
							{{audio?'重新录制':'开始录音'}}
						</view>
					</u-cell>
				</sound-recording>
				
getRecording(e) {
				console.log(e)
				this.audio = e
			},
喜欢