IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 兼容小程序和app安卓 录音功能uniapp -> 正文阅读

[移动开发]兼容小程序和app安卓 录音功能uniapp

这是一个按钮录音弹窗:你也可你自己换成别的!
点击保存会返回 录音的 路径 通过 v-model 绑定的!(你也可以自己写个emit 返回方法,)

我代码中有 我项目录音转文字的接口,使用者注意吧这些删除了就行

# 要删除的(就这俩)
	import {
		usualUploadFileOne,
		removeFile,
		usualGetFileList,
		getSpeech
	} from '@/common/api/ip'

try{
	let res = await getSpeech({ filePath: this.recordFile.fullPath }, { myFile: this.recordFile.fullPath })
	this.loading = false
	this.$refs.uToast.show({ title: '录音转文字成功,请粘贴内容', type: 'success' })
	this.$emit('input', JSON.parse(res.data.data)[0])
		this.releaseManger()
	}catch(e){
		this.loading = false
		this.$refs.uToast.show({ title: e, type: 'warning' })
	}

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

用到 scss、 组件库、图片位置

uview

注意: 项目没有 uview 组件库的,自己想办法吧!该录音也没用什么,就用了个 进度条和按钮, 自己整的替换了就行

图片资源:三个
在这里插入图片描述

注意: 图片资源自己去 https://www.iconfont.cn/上找 长这样(我不知道怎么传!)
在这里插入图片描述
注意: 俩svg 和一个png ;命名和 图片格式别搞错了!导入到对应的 static/img中

下面是完整代码 和引用(记得删了 转文字接口)

文件名 fs-audio

<template>
	<view>

		<view>
			<slot>
				<u-button type="default" @click="openRecordDialog">录音转文字</u-button>
			</slot>
		</view>
		<!-- 录音弹窗 -->
		<u-mask :show="toggleDialog" :mask-click-able="false">
			<view class="recordWrap">
				<view class="top_tip">{{topTipText}}</view>
				<view class="progress_time_wrap" v-if="toggleDialog">
					<view class="record_progress">
						<u-circle-progress bg-color="#000" active-color="#2979ff" :percent="record_progress_time">
								<image style="width: 70%;height: 70%;" mode="aspectFit" src="/static/img/arecord.png"></image>
						</u-circle-progress>
					</view>
					<view class="record_time">{{record_formate_time}}</view>
				</view>
				<view class="record_control">
					<view class="btn record_reset" @click="resetRecord" v-if="record_status >= 4">
						<view class="in_btn reset_btn"></view>
						<view class="btn_title">重新录制</view>
					</view>
					<view class="btn record_start" @click="startRecord">
						<view class="in_btn l_btn" :class="{start:record_status == 0 || record_status >=4,pause: record_status == 1 || record_status== 3}"></view>
						<view class="in_btn r_btn" :class="{start:record_status == 0 || record_status >=4,pause: record_status == 1 || record_status== 3}"></view>
						<template v-if="record_status == 2">
							<image style="width: 100%;height: 100%;margin-left: 6rpx;" src="/static/img/play.svg" alt=""></image>
						</template>
						<view class="btn_title">{{startBtnText}}</view>
					</view>
					<view class="btn record_reset" @click="playRecord" v-if="record_status >= 4">
						<view v-if="record_status == 4" class="in_btn play l_play_btn">
							<image style="width: 100%;height: 100%;margin-left: 6rpx;" src="/static/img/play.svg" alt=""></image>
						</view>
						<template v-if="record_status == 5">
							<view class="in_btn pause r_end_btn"></view>
							<view class="in_btn pause r_end_btn"></view>
						</template>
						<view class="btn_title">{{playBtnText}}</view>
					</view>
					<!-- #ifdef MP-WEIXIN -->
					<view class="btn record_start" @click="saveRecord" v-if="record_status == 2">
						<view class="in_btn" style="width: 100%; transform: translateX(-4rpx);background-color: #ff000000;">
							<image style="width: 100%;height: 100%;margin-left: 6rpx;" src="/static/img/dui.svg" alt=""></image>
						</view>
					</view>
					<!-- #endif -->
				</view>
				<!-- <view>
					{{recordFile.name}}
				</view>
				<view>
					{{recordFile.fullPath}}
				</view> -->
				<view class="action_btn">
					<u-button :ripple="true" :plain="true" class="btn" @click="successClick">确定</u-button>
					<u-button :ripple="true" :plain="true" class="btn" @click="cancalClick">取消</u-button>
				</view>
				<!-- <view class="footer">
					<button type="default" @click="toggleDialog = false">关闭</button>
				</view> -->
			</view>
		</u-mask>



		<!-- 加载 -->
		<u-mask :show="loading" @click="loading = false">
		  <view class="load_more_m">
		    <u-loading mode="circle" color="#169ef9" />
		    <view class="word">录音转文字中...</view>
		  </view>
		</u-mask>
		<!-- 提示 -->
		<u-toast ref="uToast" />
		
	</view>
</template>

<script>
	import {
		usualUploadFileOne,
		removeFile,
		usualGetFileList,
		getSpeech
	} from '@/common/api/ip'
	export default {
		name: "fs-audio",
		props:{
			value: String,
			time:{type:Number, default: 600},//录音可录制的总时常
		},
		data() {
			return {
				loading: false,
				//共
				toggleDialog: false, //录音弹窗切换
				record_time: 0, //录音时间
				record_time_copy: 0, //录音时间
				record_progress_time: 0, //录音进度时间
				record_formate_time: '00:00:00', //录音格式化时间
				record_status: 0,//录音状态 0未开始,1开始,2暂停,3继续,4结束录,5播放,6重新录
				record_img: '',
				startBtnText:'开始',//录制按钮文字
				playBtnText:'播放录音',//录制按钮文字
				topTipText: '',
				timer: null,//定时器
				recordFile: {},//录音文件
				//录
				recordInstance: null, //录音对象

				//播
				playInstance: null, //录音对象


				tempFilePath:''
			};
		},
		methods: {
			//点击取消
			cancalClick() {
				uni.showModal({
					title: "取消录制",
					content: "是否取消录制?",
					success: (res) => {
						if (res.confirm) {
							this.releaseManger()
						}
					}
				})
			},
			//释放管理器
			releaseManger() {
				this.record_status = 0
				this.recordInstance = null
				this.playInstance = null
				this.toggleDialog = false
			},
			//点击确定
			async successClick() {
				if (!this.recordFile.fullPath) {
					this.$refs.uToast.show({title: '请录音后再保存',type: 'warning'})
					return;
				}
				//录音转文字
				this.loading = true
				try{
					// await this.getSpeech()
					let res = await getSpeech({ filePath: this.recordFile.fullPath }, { myFile: this.recordFile.fullPath })
					this.loading = false
					this.$refs.uToast.show({ title: '录音转文字成功,请粘贴内容', type: 'success' })
					this.$emit('input', JSON.parse(res.data.data)[0])
					this.releaseManger()
				}catch(e){
					this.loading = false
					this.$refs.uToast.show({ title: e, type: 'warning' })
					//TODO handle the exception
				}
				
			},
			// 播放录音
			playRecord() {
				if(this.record_status == 4) {
					// #ifdef APP-PLUS
					this.playInstance = plus.audio.createPlayer(this.recordFile.fullPath)
					this.playInstance.addEventListener('play',()=> {
						this.record_time = 0
						this.record_status = 5
						this.$nextTick(() =>{
							this.setTime()
						})
					})
					this.playInstance.play((res) => {
						console.log('播放成功完成')
						this.record_time = this.record_time_copy
						this.record_status = 4
					},(err) => {
						console.log('播放失败')
					})
					// #endif
					// #ifdef MP-WEIXIN
					this.playInstance = uni.createInnerAudioContext()
					this.playInstance.src = this.recordFile.fullPath
					//音频播放事件
					this.playInstance.onPlay(() => {
						console.log('开始播放')
						this.record_time = 0
						this.record_status = 5
						this.$nextTick(() =>{
							this.setTime()
						})
					})
					// 音频自然播放结束事件/
					this.playInstance.onEnded(() => {
						console.log('播放结束')
						this.record_time = this.record_time_copy
						this.record_status = 4
					})
					this.playInstance.play()
					// #endif
				}else {
					this.playInstance.stop()
					this.record_status = 4
					this.record_time = this.record_time_copy
				}
			},
			//初始化数据
			initData() {
				this.record_time = 0, //录音时间
				this.record_progress_time = 0, //录音进度时间
				this.record_formate_time = '00:00:00', //录音格式化时间
				this.clearTime()
			},
			//初始化对象
			init() {
				
			},
			// #ifdef MP-WEIXIN
			
			// #endif
			// 重置录音
			resetRecord() {
				this.record_status = 0
			},
			
			//录音弹窗切换
			openRecordDialog() {
				console.log('录音弹窗切换', this.toggleDialog)
				this.getRecordSetting()
				// this.toggleDialog = !this.toggleDialog
			},
			//创建录音列表
			createAudioList() {
				
			},
			//开始录音
			startRecord() { 
				if(this.record_status == 4) {
					this.$refs.uToast.show({ title: '请点击重新录制再进行此操作', type: 'warning' })
				}
				// #ifdef APP-PLUS
				this.recordInstance = plus.audio.getRecorder();
				if(this.record_status == 0) {
					this.recordInstance.record({ filename: '_doc/audio/' }, (recordFile) => {
						console.log(recordFile,'保存录音----')
						plus.io.resolveLocalFileSystemURL(recordFile, (entry) => {
							console.log(entry,'转换后的录音地址')
							this.recordFile = entry
							// this.getSpeech(entry.fullPath)
						}, (e) => {
							this.$refs.uToast.show({ title: '读取录音文件错误', type: 'warning' })
						});
					}, (e) => {
						console.log(e,)
						this.$refs.uToast.show({ title: '录音失败', type: 'warning' })
					});
				}else {
					this.record_status = 4//结束录
					this.record_time_copy = this.record_time
					this.recordInstance.stop()
				}
				if(this.record_status == 0) this.record_status = 1
				// #endif
				console.log(this.recordInstance,'this.recordInstance')
				// #ifdef MP-WEIXIN
				this.recordInstance = uni.getRecorderManager()
				this.setSetting()
				// #endif
				
				
				 
				
				
				
				
				
			},
			//小程序录音功能
			MPWEIXINstart() {
				console.log(this.recordInstance,'this.recordInstance')
				//监听开始
				this.recordInstance.onStart((res) => {
					if(this.record_status == 0) this.record_status = 1
					console.log('开始录音')
				})
				//监听暂停
				this.recordInstance.onPause(() => {
					console.log('监听暂停')
					this.record_status = 2
					this.record_time_copy = this.record_time
				})
				//监听继续
				this.recordInstance.onResume(() => {
					console.log('监听继续')
					this.record_status = 3
					this.record_time_copy = this.record_time
				})
				//监听结束
				this.recordInstance.onStop((res) => {
					console.log(res.tempFilePath,'监听结束')
					this.record_status = 4
					this.recordFile.fullPath = res.tempFilePath
					this.recordFile.name = res.tempFilePath
				})
				//监听错误
				this.recordInstance.onError((err) => { console.log(err) })
				if(this.record_status == 0) {
					this.recordInstance.start({duration:600000,format:'wav'});
					return;
				}else if(this.record_status == 1) {//暂停
					this.recordInstance.pause()
					return;
				}else if(this.record_status == 2) {//继续
					this.recordInstance.resume()
					return;
				}else if(this.record_status == 3) {//暂停
					this.recordInstance.pause()
					return;
				}
			},
			//录音完成
			saveRecord() {
				if(this.record_status != 4)
				this.recordInstance.stop()
			},
			//设置定时器
			setTime() {
				if(this.timer) return;
				this.timer = setInterval(() => {
					if(this.record_time >= this.time){
						return this.record_status = 4
					}
					this.record_time = this.record_time + 1
				},1000)
			},
			//清除定时器
			clearTime() {clearInterval(this.timer);this.timer = null},
			//获取录音权限
			getRecordSetting() {
				// console.log(uni.getSetting,'uni.getSetting')
				// #ifdef MP-WEIXIN
				this.toggleDialog = !this.toggleDialog
				// #endif

				// #ifdef APP-PLUS
				this.confirmPlatform()
				// #endif
			},
			// #ifdef MP-WEIXIN
			setSetting() {
				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: (res) => {
									if (res.cancel) {
										this.$refs.uToast.show({
											title: '拒绝授权!',
											type: 'warning'
										})
									} else if (res.confirm) {
										uni.openSetting({
											success: (dataAu) => {
												console.log(dataAu, 'openSetting')
												if (dataAu.authSetting[
														"scope.record"] == true) {
													this.$refs.uToast.show({
														title: '授权成功!',
														type: 'success'
													})
													//再次授权,调用wx.getLocation的API
													this.MPWEIXINstart()
												} else {
													this.$refs.uToast.show({
														title: '授权失败!',
														type: 'warning'
													})
												}
											}
										})
									}
								}
							})
						} else if (res.authSetting['scope.record'] == undefined) {
							//调用wx.getLocation的API
							console.log('首次授权')
				
							this.MPWEIXINstart()
						} else {
							//调用wx.getLocation的API
							this.MPWEIXINstart()
						}
					},
					fail(err){
						console.log(err,'fail')
					},
					complete(err) {
						console.log(err,'getSetting')
					}
				})
				
			},
			// #endif
			
			
			// #ifdef APP-PLUS
			// 确定运行平台
			confirmPlatform() {
				switch (uni.getSystemInfoSync().platform) {
					case 'android':
						console.log('运行Android上');
						this.androidGetRecordSetting()
						break;
					case 'ios':
						console.log('运行iOS上');
						break;
					default:
						console.log('运行在开发者工具上');
						break;
				}
			},
			//android权限设置
			androidGetRecordSetting() {
				plus.android.requestPermissions(['android.permission.RECORD_AUDIO'], (e) => {
					console.log(e.length > 0, 'e-----android权限设置')
					if (e.deniedAlways.length > 0) { //权限被永久拒绝
						// plus.runtime.openURL("app-settings://");
						var main = plus.android.runtimeMainActivity();
						var Intent = plus.android.importClass("android.content.Intent");
						//可能应该直接进入应用列表的权限设置?=> android.settings.APPLICATION_SETTINGS
						var mIntent = new Intent('android.settings.APPLICATION_SETTINGS');
						main.startActivity(mIntent);
						// 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启
						this.$refs.uToast.show({
							title: '该功能需要录音权限,请在权限设置中进行授权!'
						})
						console.log('Always Denied!!! ' + e.deniedAlways.toString());
					}
					if (e.deniedPresent.length > 0) { //权限被临时拒绝
						this.toggleDialog = !this.toggleDialog
						// 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限
						console.log('Present Denied!!! ' + e.deniedPresent.toString());
					}
					if (e.granted.length > 0) { //权限被允许
						//调用依赖获取定位权限的代码
						this.toggleDialog = !this.toggleDialog
						console.log('Granted!!! ' + e.granted.toString());
					}
				}, (e) => {
					// this.toggleDialog = !this.toggleDialog
					// console.log('Request Permissions error:' + JSON.stringify(e));
				});
			},
			// #endif
			//数字转时间
			secondsFormat(sec){
			   let hour = Math.floor(sec / 3600)
			   let minute = Math.floor((sec - hour * 3600) / 60)
			   let second = sec - hour * 3600 - minute * 60
			   if (hour < 10) { hour = "0" + hour; }
			   if (minute < 10) { minute = "0" + minute; }
			   if (second < 10) { second = "0" + second; }
			   return hour + ":" + minute + ":" + second;
			},
			//录音转文字
			async getSpeech(tempFilePath) {
				await getSpeech({ filePath: this.tempFilePath || tempFilePath }, { myFile: this.tempFilePath || tempFilePath })
					.then(res => {
						console.log(res, '录音转文字')
						this.$emit('input', JSON.parse(res.data.data)[0])
						this.$refs.uToast.show({ title: '录音转文字成功,请粘贴内容', type: 'success' })
					})
			},
		},
		watch: {
			record_time(newValue, oldValue) {
				if(newValue == 0) {
					this.record_progress_time = 0
					this.record_formate_time = '00:00:00'
				}else {
					this.record_progress_time = (newValue * 100) / this.time
					this.record_formate_time = this.secondsFormat(newValue)
				}
			},
			//录音状态0未开始,1开始,2暂停,3继续,4结束录,5播放,6重新录
			record_status(newValue, oldValue) {
				switch(newValue) {
					case 0 : this.initData() ;this.startBtnText = '开始';this.topTipText=""; break;
					case 1 : this.setTime() ;this.startBtnText = '暂停' ;this.topTipText="录音中..."; break;
					case 2 : this.clearTime() ;this.startBtnText = '继续' ;this.topTipText="录音中..."; break;
					case 3 : this.setTime() ;this.startBtnText = '暂停'; this.topTipText="录音中..."; break;
					case 4 : this.clearTime() ;this.startBtnText = '录制结束' ; this.playBtnText = '播放录音';this.topTipText=""; break;
					case 5 : this.clearTime() ;this.playBtnText = '录音播放中';this.topTipText="播放中..."; break;
				}
			},
		},
		mounted() {
			this.init() //初始化对象
		},
		computed:{
			//格式化已经录制的时间
			formatRecordTime() {
				return this.secondsFormat(this.record_time)
			}
		}
	}
</script>

<style lang="scss">
	//录音弹窗样式
	.recordWrap {
		width: 100%;
		height: 100vh;
		background-color: #000000;
		position: relative;
		z-index: 999;
		box-sizing: border-box;
		padding-bottom: 100rpx;
		overflow: hidden;
		color: white;
		.progress_time_wrap{
			margin-top: 200rpx;
			display: flex;
			align-items: center;
			justify-content: center;
			flex-direction: column;
		}
		.top_tip{
			position: absolute;
			top: 20rpx;
			left: 0;
			width: 100%;
			text-align: center;
			height: 60rpx;
			line-height: 60rpx;
		}
		.record_control{
			display: flex;
			padding: 100rpx;
			justify-content: center;
			align-items: center;
			.btn{
				position: relative;
				margin: 0 40rpx;
				transition: all .5s;
				background: #d8d6d6;
				box-shadow: 0 0 10px #d8d6d6;
				width: 100rpx;
				height: 100rpx;
				border-radius: 50%;
				display: flex;
				justify-content: space-around;
				align-items: center;
				padding: 20rpx;
				box-sizing: border-box;
				&:active{
					transform: scale(0.8);
				}
				.btn_title{
					position: absolute;
					top: 100%;
					width: 100%;
					font-size: 28rpx;
					text-align: center;
					white-space: nowrap;
				}
				.in_btn{
					background-color: red;
					transition: all .5s;
					height: 100%;
					&.start {
						width: 40rpx;
						&.start.l_btn{
							border-radius: 40rpx 0 0 40rpx;
						}
						&.start.r_btn{
							border-radius:  0 40rpx 40rpx 0;
						}
					}
					&.pause {
						width: 20rpx;
						border-radius: 10rpx
					}
					&.reset_btn{
						width: 100%;
						height: 100%;
						border-radius: 20rpx;
						
					}
					&.play{
						width: 100%;
						height: 100%;
						border-radius: 10rpx;
						&.play.l_play_btn{
							background-color: transparent;
							// transform: rotate(-45deg);
						}
						&.play.r_end_btn{
							background-color: transparent;
						}
					}
					&.end{
						width: 20rpx;
						border-radius: 10rpx
					}
				}
			}
		}
		.action_btn{
			position: absolute;
			z-index: 1;
			bottom: 8rpx;
			left: 0;
			width: 100%;
			display: flex;
			justify-content: space-around;
			align-items: center;
			box-sizing: border-box;
			.btn{
				flex: 1;
				margin: 32rpx;
			}
		}
		.footer{
			
		}
	}
	.load_more_m {
		margin: 33vh auto auto;
		width: 300rpx;
		height: 200rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		background: #fff;
		border-radius: 20rpx;
		flex-direction: column;
		.word {
			margin-top: 24rpx;
			letter-spacing: 0.1em;
		}
	}
</style>

调用:引用、注册、使用(这儿只写 使用)

<fs-audio v-model="CONTENT"></fs-audio>

ok 完事了, 有问题就问,我还会完善的!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:41:20  更:2022-02-28 15:44:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 16:34:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码