当前位置:   article > 正文

uniapp录音方法的使用说明_uniapp 录音

uniapp 录音

uniapp录音方法的使用说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

设计思路:

1、中间按钮点击录音开始,可以进行暂停,继续操作
2、录音时可以进行取消,完成操作
3、录音完成可以点击听录好的音频
4、可以将录好的音频删除重新录音

需要注意的地方:

1、开始录音时需要检测是否是H5页面,H5页面没有录音功能,app端需要检测是否有录音权限
开始录音methodfile.js

export async function startRecording() {
	return new Promise((resolve, reject) => {
		try {
			if (!recorderManager) {
				recorderManager = uni.getRecorderManager();
			}
			// 是否开启录音权限
			let permission = plus.navigator.checkPermission('RECORD');
			if (permission == 'authorized') {
				// 应用有录音权限,可以进行录音操作
				recorderManager.start({
					duration: profile.duration // 录音时长:3分钟
				});
			} else {
				// 应用没有录音权限,可能需要请求用户授予录音权限
				// 或者显示一个提示,告知用户需要录音权限才能进行操作
				reject('应用没有录音权限');
			}
		} catch (e) {
			// 如果出现错误,调用 reject 函数并传递错误信息
			reject('请在app和小程序端体验录音,Uni官方明确H5不支持getRecorderManager, 详情查看Uni官方文档');
		}
	});
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

2、录音暂停清除录音计时的定时器,但是不清除秒数时长,这里需要定义一个定时器times,秒数增加num(这个在暂停清除定时器时不被清除),字符串秒数显示second
暂停录音record.vue

pauseRecording() {
    let t = this
    t.isStop = true
    audioRecorder.pauseRecording();
    clearInterval(t.times)
},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3、播放已录好的音频需要用到音频播放,详见下一个文档
4、删除录好的音频需要判断一下是否在播放,如果在播放就结束播放然后删除录好的音频

附上源码:

vue文件:record.vue

<template>
	<view class="page-show">
		<view class="row-layout" style="justify-content: space-between;margin-top: 22rpx;" v-if="isFinish">
			<view class="voice_con row-layout" @click="playVoice()">
				<image class="yy_img" src="/static/image/pause.png" v-show="playing"></image>
				<image class="yy_img" src="/static/image/play.png" v-show="!playing"></image>
				<view class="voiceAniation" style="margin: 0 10rpx 0 22rpx;">
					<view class="em" v-for="(item,index) in 8" :key="index" :style="playing?'':'animation: none;'">
					</view>
				</view>
				<view class="time_long">{{second}}</view>
			</view>
			<image src="/static/image/delete.png" mode="widthFix" style="width: 48rpx;" @click="delVoice()">
			</image>
		</view>
		<view class="page-record">
			<!-- 录音背景光圈:当不处于暂停和处于录音中出现 -->
			<view class="bgCircle" v-show="!isStop&&isVoicing">
				<!-- 外层光圈 -->
				<view class="bgCircleOut">
				</view>
				<!-- 内层光圈 -->
				<view class="bgCircleIn">
				</view>
			</view>
			<!-- 语音输入的按钮 -->
			<view class="voice_type" v-show="!isFinish">
				<!-- 开始录音按钮 -->
				<view class="vertical_center" v-show="!isVoicing" @click="startRecording()">
					<view class="start_record">开始记录</view>
					<!-- 点击开始录音:isVoicing=true正在录音状态 -->
					<view class="entoch_btn">
						<image src="/static/image/recording.png" mode="widthFix"></image>
					</view>
				</view>
				<!-- 正在录音 -->
				<view class="vertical_center" v-show="isVoicing">
					<!-- 文字写在外面是因为文字不参与垂直居中 -->
					<view class="start_record" v-show="!isStop">
						<text>{{second==''?'0:00':second}}</text>
					</view>
					<view class="start_record" v-show="isStop">继续</view>
					<view class="three-btn row-layout" style="justify-content: space-between;">
						<!-- 取消录音:×按钮 -->
						<view class="voice_operate row-layout" style="background: #D5D5D5;" @click="cancelVoice()">
							<image src="/static/image/cancel.png" mode="widthFix"></image>
						</view>
						<!-- 暂停按钮 -->
						<view class="voice_middle" v-show="!isStop" @click="pauseRecording()">
							<!-- 正在录音状态 -->
							<view class="entoch_btn">
								<image src="/static/image/pauserecord.png" mode="widthFix"></image>
							</view>
						</view>
						<!-- 继续按钮 -->
						<view class="voice_middle" v-show="isStop" @click="resumeRecording()">
							<!-- 暂停录音状态 -->
							<view class="entoch_btn">
								<image src="/static/image/recording.png" mode="widthFix"></image>
							</view>
						</view>
						<!-- 完成录音:√按钮 -->
						<view class="voice_operate row-layout" @click="finishVoice()">
							<image src="/static/image/finish.png" mode="widthFix"></image>
						</view>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import * as audioRecorder from '@/audioRecorder/methodfile.js'; //音频封装的方法文件
	import profile from '@/audioRecorder/profile.js'; //音频封装的方法文件
	export default {
		data() {
			return {
				isVoicing: false, //是否是录音状态
				isFinish: false, //是否录音完成
				isStop: false, //录音状态是否暂停
				voiceList: [],
				num: 0,
				second: '',
				playing: false,
                times: '', //定时器
			}
		},
		methods: {
			//删除录音
			delVoice() {
				this.isFinish = false
				this.voiceList = []
				this.num = 0
				this.second = ''
				audioRecorder.playStop();
			},
			//定时器:录音计时
			getTimeInterval() {
				let t = this
				t.times = setInterval(() => {
					++t.num;
					const minute = Math.floor(t.num / 60); // 获取分钟数
					const miao = (t.num % 60) < 10 ? '0' + (t.num % 60) : (t.num % 60);
					t.second = minute + ':' + miao
					// 录音到规定时长会自动停止录音,需要做一些完成录音的状态修改,所以调用一下录音完成的方法
					if (t.num == (profile.duration / 1000)) {
						t.finishVoice();
					}
				}, 1000)
			},
			//开始录音
			startRecording() {
				let t = this
				t.isVoicing = true
				t.getTimeInterval();
				audioRecorder.startRecording().then((result) => {
					uni.showToast({
						title: result,
						duration: 500
					});
				}).catch((erro) => {
					this.cancelVoice();
					uni.showModal({
						title: '录音失败',
						content: erro
					})
				})
			},
			//暂停录音
			pauseRecording() {
				let t = this
				t.isStop = true
				audioRecorder.pauseRecording();
				clearInterval(t.times)
			},
			//继续录音
			resumeRecording() {
				let t = this
				t.isStop = false
				audioRecorder.resumeRecording();
				this.getTimeInterval();
			},
			//停止录音
			stopRecording() {
				let t = this
				clearInterval(t.times) // 清除定时器
				audioRecorder.stopRecording().then(tempFilePath => {
					//保存录音文件的变量清空,避免出现取消的录音存在(添加录音时,只能添加一条的情况)
					t.voiceList = []
					t.voiceList.push({
						path: tempFilePath,
						second: t.second
					});
				}).catch(error => {
					t.$.toast('录音出错:', error)
				});
			},
			// ×取消录音,所有状态回到最初(isVoicing不是录音状态,isFinish不是完成录音,isStop不是暂停状态,isInputType显示选择输入方式)
			cancelVoice() {
				this.delVoice();
				this.changeStatus();
				this.stopRecording();
			},
			//√完成录音(isVoicing不是录音状态,isFinish录音完成状态)
			finishVoice() {
				if (this.num < 1) {
					uni.showToast({
						icon: 'error',
						title: '录音时间太短',
						duration: 500
					});
					return
				}
				this.stopRecording()
				this.isFinish = true
				this.changeStatus();
			},
			changeStatus() {
				this.isVoicing = false
				this.isStop = false
			},
			//播放语音
			playVoice() {
				if (this.playing == false) { //开始播放
					this.playing = true;
					audioRecorder.playVoiceTwo(this.voiceList[0].path, this.currentTime)
					// 播放时间到自动停止并销毁音频实例,释放空间
					setTimeout(() => {
						this.playing = false;
						this.currentTime = 0
						audioRecorder.playStop();
						audioRecorder.playDestroy();
					}, this.num * 1000)
				} else { //暂停播放
					this.playing = false;
					audioRecorder.playPause().then(res => {
						this.currentTime = res
					});
				}
			},
		}
	}
</script>

<style lang="scss" scoped>
	.page-show{
		margin-top: 20%;
	}
	.voice_con {
		background: skyblue;
		border-radius: 80rpx;
		padding: 11rpx 36rpx 11rpx 22rpx;

		.yy_img {
			width: 50rpx;
			height: 50rpx;
			margin-left: 22rpx;
			margin-right: 10rpx;
		}

		.time_long {
			font-size: 28rpx;
			color: white;
		}
	}

	.page-record {
		position: fixed;
		bottom: 0;
		left: 0;
		width: 100%;
		height: 350rpx;

		.voice_type {

			.vertical_center {
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;

				.start_record {
					font-size: 36rpx;
					font-weight: bold;
					text-align: center;
					margin: 4% 0;
				}

				.entoch_btn {
					background: linear-gradient(180deg, rgba(19, 212, 154, 1) 0%, rgba(140, 255, 225, 1) 100%);
					box-shadow: 0 4rpx 12rpx 2rpx #9CFFD0;
					padding: 24rpx;
					border-radius: 50%;
					width: 100rpx;
					height: 100rpx;

					image {
						width: 100%;
						height: 100%;
					}
				}

				.three-btn {
					width: 100%;

					.voice_operate {
						width: 166rpx;
						height: 88rpx;
						border-radius: 100rpx;
						background: rgba(19, 212, 154, 1);
						justify-content: center;

						image {
							width: 66rpx;
						}
					}

					.voice_middle {
						text-align: center;
					}
				}
			}
		}

		.bgCircle {
			position: fixed;
			bottom: 0;
			width: 100%;
			height: 320rpx;
			z-index: -1;


			.bgCircleOut {
				position: absolute;
				left: 29%;
				transform: translateX(-29%);
				width: 320rpx;
				/* 宽度 */
				height: 320rpx;
				/* 高度,为宽度的一半,形成半圆 */
				border-radius: 50%;
				background-color: rgba(253, 255, 254, 0.38);
				box-shadow: 0rpx -10rpx 14rpx 12rpx rgba(0, 0, 0, 0.38);
				/* 光圈的颜色 */
				animation: pulse 1.5s infinite;
				/* 应用名为 "pulse" 的动画,无限循环 */
			}

			.bgCircleIn {
				position: absolute;
				bottom: 16%;
				left: 35.5%;
				transform: translateX(-35.5%);
				width: 220rpx;
				/* 宽度 */
				height: 220rpx;
				/* 高度,为宽度的一半,形成半圆 */
				border-radius: 50%;
				background-color: rgba(253, 255, 254, 0.38);
				box-shadow: 0rpx -10rpx 14rpx 12rpx rgba(196, 207, 207, 0.38);
				/* 光圈的颜色 */
				animation: pulsetwo 1.3s infinite;
				/* 应用名为 "pulse" 的动画,无限循环 */
			}

		}

		@keyframes pulse {
			0% {
				transform: scale(1);
				/* 初始大小 */
				opacity: 0.3;
				/* 初始透明度 */
			}

			50% {
				transform: scale(1.1);
				/* 放大到1.2倍大小 */
				opacity: 0.3;
				/* 透明度减小 */
			}

			100% {
				transform: scale(1);
				/* 回到初始大小 */
				opacity: 0.3;
				/* 透明度恢复 */
			}
		}

		@keyframes pulsetwo {
			0% {
				transform: scale(1);
				/* 初始大小 */
				opacity: 0.8;
				/* 初始透明度 */
			}

			50% {
				transform: scale(1.1);
				/* 放大到1.2倍大小 */
				opacity: 0.8;
				/* 透明度减小 */
			}

			100% {
				transform: scale(1);
				/* 回到初始大小 */
				opacity: 0.8;
				/* 透明度恢复 */
			}
		}
	}
</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375

方法文件:methodfile.js

// 全局定义录音
let recorderManager = uni.getRecorderManager();

/**
 * 录音播放、暂停、继续、结束方法
 */
// 开始录音
export async function startRecording() {
	return new Promise((resolve, reject) => {
		try {
			if (!recorderManager) {
				recorderManager = uni.getRecorderManager();
			}
			// 是否开启录音权限
			let permission = plus.navigator.checkPermission('RECORD');
			if (permission == 'authorized') {
				// 应用有录音权限,可以进行录音操作
				recorderManager.start({
					duration: profile.duration // 录音时长:3分钟
				});
			} else {
				// 应用没有录音权限,可能需要请求用户授予录音权限
				// 或者显示一个提示,告知用户需要录音权限才能进行操作
				reject('应用没有录音权限');
			}
		} catch (e) {
			// 如果出现错误,调用 reject 函数并传递错误信息
			reject('请在app和小程序端体验录音,Uni官方明确H5不支持getRecorderManager, 详情查看Uni官方文档');
		}
	});
}
// 暂停录音
export function pauseRecording() {
	recorderManager.pause();
}
// 继续录音
export function resumeRecording() {
	recorderManager.resume();
}
// 结束录音
export function stopRecording() {
	return new Promise((resolve, reject) => {
		// 监听录音结束,获取音频临时路径
		recorderManager.onStop(res => {
			resolve(res.tempFilePath);
		});
		// 停止录音
		recorderManager.stop();
	});
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

配置文件:profile.js

let DURATION = 180000 //录音时长,毫秒
let VOLUME = 0.2  //音频播放音量0~1

const profile = {
	duration: DURATION,
	volume: VOLUME
};

export default profile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/565574
推荐阅读
相关标签
  

闽ICP备14008679号