由该博客 改成 uniapp形式

swift开发录音权限 app录音功能开发_swift开发录音权限

<template>
	<div>
		<u-button class="btn1" @click="selectType">录音转文字</u-button>
		<u-action-sheet :list="selectTypeList" v-model="isSelectType" @click="handleSelectType"></u-action-sheet>
		<my-mask :visible="showAudioMark" @confirmClick="successClick('')" title="录音" @cancalClick="cancalClick">
			<view class="time">{{status==0?'录音时长':(status==3?'录音已完成':'正在录音中')}}:{{time}} 秒</view>
			<view class="btn">
				<view :class="status==3?'show':'hide'" @click="reset" hover-class="jump-hover">重新录制</view>
				<view :class="status==3 && playStatus==0?'show':'hide'" @click="bofang" hover-class="jump-hover">{{playStatus==1?'录音播放中':'播放录音'}}</view>
			</view>
			<view class="progress">
				<text class="txt">最大录音时长({{duration/1000}}秒 = {{duration/60000}}分钟)</text>
				<progress :percent="time*(100/(duration/1000))" border-radius="10" color="green" stroke-width="10" />
			</view>
			<view class="anniu">
				<view :class="status==0?'row':'no-clicking'" @click="getAudioSetting" hover-class="jump-hover">开始</view>
				<view :class="status==1?'row':'no-clicking'" @click="zanting" hover-class="jump-hover">暂停</view>
				<view :class="status==2?'row':'no-clicking'" @click="jixu" hover-class="jump-hover">继续</view>
				<view :class="(status==1 || status==2)?'row':'no-clicking'" @click="tingzhi" hover-class="jump-hover">停止</view>
			</view>
		</my-mask>
		<loading-mask :show.sync="showMask"></loading-mask>
	</div>
</template>

<script>
	import {usualUploadFileOne,removeFile,usualGetFileList,getSpeech} from '@/common/api/ip'
	const recorderManager = uni.getRecorderManager()
	const innerAudioContext = uni.createInnerAudioContext();
	var init
	export default {
		name: "audio-mask",
		data() {
			return {
				showAudioMark: false,//录音弹窗切换
				isSelectType: false,//选择录音上传弹窗切换
				showMask: false,
				selectTypeList: [{
					text: '上传录音'
				}, {
					text: '现场录音'
				}],
				selectIndex: null,
				time: 0, //录音时长
				duration: 600000, //录音最大值ms 600000/10分钟
				tempFilePath: "", //音频路径
				status: 0, //录音状态 0:未开始录音 1:正在录音 2:暂停录音 3:已完成录音
				playStatus: 0, //录音播放状态 0:未播放 1:正在播放
			};
		},
		props: {
			value: String
		},
		methods: {
			//选择录音方法弹窗切换
			selectType() {
				this.isSelectType = true
			},
			//选择录音上传方法
			handleSelectType(index) {
				console.log(index)
				this.selectIndex = index
				if(index == 1) {
					
					this.showAudioMark = true
				}else if(index == 0) {
					// this.showAudioMark1 = true
					this.uploadFile()
				}
			},
			//上传文件
			uploadFile() {
				uni.chooseMessageFile({
					count: 1,
					type: 'wav',
					success: (res) => {
						console.log(res,'uploadFileres')
						/**
						 *	name: "新文件.wav"
							path: "http://tmp/slaQis9pHQM6677f96ecd24d1e0944fa06303441a06f.wav"
							size: 133846
							time: 1635139223
							type: "file"*/
						this.successClick(res.tempFiles[0].path)
					},
					fail(err) {
						console.log(err,'uploadFileerr')
					}
				})
			},
			//点击取消
			cancalClick() {
				uni.showModal({
					title: "取消录制",
					content: "是否取消录制?",
					success:(res) => {
						if (res.confirm) {
							clearInterval(init) //清除定时器
							innerAudioContext.stop()
							this.time = 0, //录音时长
							this.tempFilePath = "" //音频路径
							this.status = 0,
							this.playStatus = 0
							this.showAudioMark = false
						}
					}
				})
			},
			//点击取消1
			cancalClick1() {
				uni.showModal({
					title: "取消上传",
					content: "是否取消上传?",
					success:(res) => {
						if (res.confirm) {
							this.showAudioMark1 = false
						}
					}
				})
			},
			//点击保存
			successClick(tempFilePath) {
				if(this.selectIndex == 1 && !this.tempFilePath ) {
					if(!this.tempFilePath){
						uni.showToast({
							title: '请录音后再保存',
							icon:'none'
						})
						return;
					}
				}
				this.showMask = true
				console.log(tempFilePath,this.tempFilePath,'保存成功')
				this.showAudioMark = false
				getSpeech(
				{
					filePath: this.tempFilePath || tempFilePath
				}, {myFile:this.tempFilePath || tempFilePath}).then(res => {
					console.log(res,'录音转文字')
					this.$emit('input',JSON.parse(res.data.data)[0])
					uni.showToast({
						title:'录音转文字成功,请粘贴内容',
						icon: 'none'
					})
					this.showAudioMark = false
					this.showMask =false
				}).catch(err => {
					this.showMask = false
				})
				// if(!this.tempFilePath ||){
				// 	uni.showToast({
				// 		title: '请录音后再保存',
				// 		icon:'none'
				// 	})
				// 	return;
				// }else{
				// 	this.showMask = true
				// 	console.log('保存成功')
				// 	// this.$emit('confirmClick',this.tempFilePath)
				// 	// this.$emit('confirmClick',this.tempFilePath)
					
				// 	// this.$emit('update:showAudioMark', false)
				// 	this.showAudioMark = false
				// 	getSpeech({
				// 		filePath: tempFilePath || this.tempFilePath
				// 	}, {myFile:tempFilePath || this.tempFilePath}).then(res => {
				// 		console.log(res,'录音转文字')
				// 		this.showAudioMark = false
				// 		this.showMask =false
				// 	}).catch(err => {
				// 		this.showMask = false
				// 	})
				// // }
			},
			/**开始录音 */
			kaishi() {
				clearInterval(init) //清除定时器
				// 监听音频开始事件
				recorderManager.onStart((res) => {
					this.recordingTimer()
					console.log('recorder start')
					this.status = 1
				})
				//监听录音自动结束事件(如果不加,录音时间到最大值自动结束后,没获取到录音路径将无法正常进行播放)
				recorderManager.onStop((res) => {
					console.log('recorder stop', res)
					this.tempFilePath = res.tempFilePath
					this.status = 3
					this.recordingTimer(this.time)
				})
				recorderManager.start({
					duration: this.duration, //指定录音的时长,单位 ms
					sampleRate: 16000, //采样率
					numberOfChannels: 1, //录音通道数
					encodeBitRate: 96000, //编码码率
					format: 'wav', //音频格式,有效值 aac/mp3
					frameSize: 50, //指定帧大小,单位 KB
				})
				
			},
			//获取语言权限 没有权限 状态不变
			getAudioSetting() {
				uni.getSetting({
					success: (res) => {
						console.log(res, JSON.stringify(res, 'getSetting'))
						if (res.authSetting['scope.record'] != undefined && res.authSetting['scope.record'] != true) {
							uni.showModal({
								title: '请求授权录音权限',
								content: '需要获取录音权限,请确认授权',
								success: function(res) {
									if (res.cancel) {uni.showToast({title: '拒绝授权',icon: 'none'})
									} else if (res.confirm) {
										uni.openSetting({
											success: function(dataAu) {console.log(dataAu, 'openSetting')
				 							if (dataAu.authSetting["scope.record"] ==true) {
													uni.showToast({title: '授权成功',icon: 'none'})
													//再次授权,调用wx.getLocation的API
													this.kaishi();
												} else {uni.showToast({title: '授权失败',icon: 'none',})}
											}
										})
									}
								}
							})
						} else if (res.authSetting['scope.record'] == undefined) {
							//调用wx.getLocation的API
							console.log('首次授权')
				  	this.kaishi();
						} else {
				   //调用wx.getLocation的API
							this.kaishi();
						}
					},
					complete() {
						console.log('getSetting')
					}
				})
			},
			/**
			 * 暂停录音
			 */
			zanting() {
				console.log('pause')
				recorderManager.onPause(() => {
					console.log('recorder pause')
					this.status = 2
				})
				this.recordingTimer(this.time)
				recorderManager.pause()
			},

			/**
			 * 继续录音
			 */
			jixu() {
				this.status = 1
				this.recordingTimer()
				recorderManager.resume()
			},

			/**
			 * 停止录音
			 */
			tingzhi() {
				recorderManager.onStop((res) => {
					console.log('recorder stop', res)
					this.tempFilePath = res.tempFilePath
					this.status = 3
				})
				this.recordingTimer(this.time)
				recorderManager.stop()

			},

			/**
			 * 播放录音
			 */
			bofang() {
				//音频地址
				innerAudioContext.src = this.tempFilePath
				//在ios下静音时播放没有声音,默认为true,改为false就好了。
				innerAudioContext.obeyMuteSwitch = false

				//点击播放
				if (this.playStatus == 0) {
					this.playStatus = 1
					innerAudioContext.play()
				}
				// //播放结束
				innerAudioContext.onEnded(() => {
					innerAudioContext.stop()
					this.playStatus = 0
				})
			},

			//录音计时器
			recordingTimer(time) {
				var that = this
				if (time == undefined) {
					//将计时器赋值给init
					init = setInterval(function() {
						var time = that.time + 1;
						that.time = time
					}, 1000);
				} else {
					clearInterval(init)
					console.log("暂停计时")
				}
			},

			/**
			 * 重新录制
			 */
			reset() {
				var that = this
				uni.showModal({
					title: "重新录音",
					content: "是否重新录制?",
					success(res) {
						if (res.confirm) {
							that.time = 0, //录音时长
								that.tempFilePath = "" //音频路径
							that.status = 0,
								that.playStatus = 0
							innerAudioContext.stop()
						}
					}
				})
			}
		}
	}
</script>

<style lang="scss">
	.btn1{
		width: 100%;
	}
	.sound-recording {
		background-color: rgb(216, 228, 223);
		margin: 10rpx 30rpx;
		border-radius: 20rpx;
		padding: 5rpx 0rpx;
	}

	.btn {
		margin: 0rpx 100rpx;
		display: flex;
		justify-content: space-between;
		align-items: center;
	}

	.btn .show {
		padding: 10rpx;
		width: 200rpx;
		font-size: 25rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: rgb(178, 228, 228);
		border-radius: 20rpx;
		border: 5rpx solid rgb(127, 204, 214);
	}

	.btn .hide {
		padding: 10rpx;
		width: 200rpx;
		font-size: 25rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		border-radius: 20rpx;
		border: 5rpx solid #eee;
		pointer-events: none;
		background-color: rgba(167, 162, 162, 0.445);
	}

	.time {
		line-height: 70rpx;
		text-align: center;
		font-size: 30rpx;
	}

	.progress {
		margin: 20rpx;
	}

	.play {
		margin: 0rpx 20rpx;
	}

	.txt {
		display: flex;
		justify-content: center;
		line-height: 60rpx;
		font-size: 25rpx;
	}

	.anniu {
		margin: 10rpx 50rpx;
		display: flex;
		justify-content: space-between;
	}

	.row {
		display: flex;
		justify-content: center;
		align-items: center;
		border-radius: 50%;
		font-size: 25rpx;
		width: 80rpx;
		height: 80rpx;
		background-color: rgb(178, 228, 228);
		border: 5rpx solid rgb(127, 204, 214);
	}

	.jump-hover {transform: scale(0.9);}

	/*禁止点击*/

	.anniu .no-clicking {
		pointer-events: none;
		background-color: rgba(167, 162, 162, 0.445);
		display: flex;
		justify-content: center;
		align-items: center;
		border-radius: 50%;
		font-size: 25rpx;
		width: 80rpx;
		height: 80rpx;
		border: 5rpx solid rgb(241, 244, 245);
	}
</style>