这是一个按钮录音弹窗:你也可你自己换成别的!
点击保存会返回 录音的 路径 通过 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 = falsethis.$refs.uToast.show({ title: '录音转文字成功,请粘贴内容', type: 'success' })this.$emit('input', JSON.parse(res.data.data)[0])this.releaseManger()}catch(e){this.loading = falsethis.$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 = 0this.recordInstance = nullthis.playInstance = nullthis.toggleDialog = false},//点击确定async successClick() {if (!this.recordFile.fullPath) {this.$refs.uToast.show({title: '请录音后再保存',type: 'warning'})return;}//录音转文字this.loading = truetry{// await this.getSpeech()let res = await getSpeech({ filePath: this.recordFile.fullPath }, { myFile: this.recordFile.fullPath })this.loading = falsethis.$refs.uToast.show({ title: '录音转文字成功,请粘贴内容', type: 'success' })this.$emit('input', JSON.parse(res.data.data)[0])this.releaseManger()}catch(e){this.loading = falsethis.$refs.uToast.show({ title: e, type: 'warning' })//TODO handle the exception}},// 播放录音playRecord() {if(this.record_status == 4) {// #ifdef APP-PLUSthis.playInstance = plus.audio.createPlayer(this.recordFile.fullPath)this.playInstance.addEventListener('play',()=> {this.record_time = 0this.record_status = 5this.$nextTick(() =>{this.setTime()})})this.playInstance.play((res) => {console.log('播放成功完成')this.record_time = this.record_time_copythis.record_status = 4},(err) => {console.log('播放失败')})// #endif// #ifdef MP-WEIXINthis.playInstance = uni.createInnerAudioContext()this.playInstance.src = this.recordFile.fullPath//音频播放事件this.playInstance.onPlay(() => {console.log('开始播放')this.record_time = 0this.record_status = 5this.$nextTick(() =>{this.setTime()})})// 音频自然播放结束事件/this.playInstance.onEnded(() => {console.log('播放结束')this.record_time = this.record_time_copythis.record_status = 4})this.playInstance.play()// #endif}else {this.playInstance.stop()this.record_status = 4this.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-PLUSthis.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_timethis.recordInstance.stop()}if(this.record_status == 0) this.record_status = 1// #endifconsole.log(this.recordInstance,'this.recordInstance')// #ifdef MP-WEIXINthis.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 = 1console.log('开始录音')})//监听暂停this.recordInstance.onPause(() => {console.log('监听暂停')this.record_status = 2this.record_time_copy = this.record_time})//监听继续this.recordInstance.onResume(() => {console.log('监听继续')this.record_status = 3this.record_time_copy = this.record_time})//监听结束this.recordInstance.onStop((res) => {console.log(res.tempFilePath,'监听结束')this.record_status = 4this.recordFile.fullPath = res.tempFilePaththis.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-WEIXINthis.toggleDialog = !this.toggleDialog// #endif// #ifdef APP-PLUSthis.confirmPlatform()// #endif},// #ifdef MP-WEIXINsetSetting() {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的APIthis.MPWEIXINstart()} else {this.$refs.uToast.show({title: '授权失败!',type: 'warning'})}}})}}})} else if (res.authSetting['scope.record'] == undefined) {//调用wx.getLocation的APIconsole.log('首次授权')this.MPWEIXINstart()} else {//调用wx.getLocation的APIthis.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_SETTINGSvar 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.toggleDialogconsole.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 * 60if (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 = 0this.record_formate_time = '00:00:00'}else {this.record_progress_time = (newValue * 100) / this.timethis.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 完事了, 有问题就问,我还会完善的!

兼容小程序和app安卓 录音功能uniapp相关推荐

  1. uni-app实现发送到朋友圈,微信好友等功能兼容小程序app

    做小程序或app,其本都需要用到这个功能,这里详细总结一下相关步骤.大概就是实现下图的三个功能: 一,保存图片功能(小程序和APP一样) <view @click="baoimgFn& ...

  2. 打车/网约车、代驾、顺风车/拼车/快车/专车(含市内和城际)、货运(小程序、APP(安卓/苹果)、公众号、H5网页)

    打车出行平台支持打车/网约车.代驾.顺风车/拼车/快车/专车(含市内和城际).货运.租车,可快速上线运营. 打车网约车拼车平台:打车+代驾+顺风车+货运 基础功能模块 NO.1[ 乘客端 ] 01.多 ...

  3. uni-app 微信小程序 模仿 app二层楼功能

    uni-app 微信小程序 模仿 app二层楼功能 先占个坑,今天应该写不完, 后续在慢慢补全 更新 终于写完了 这个的计算量很大,我自己的安卓机测试的时候一卡一卡的,公司同事的iphone是没有问题 ...

  4. 运营版uniapp多商户商城小程序+H5+APP+商家入驻短视频社区种草直播阶梯拼团

    运营版uniapp多商户商城小程序+H5+APP+商家入驻短视频社区种草直播阶梯拼团 前后端全套源码, 支持二次开发,代码无加密! 独立商家后台 用于店铺商品管理订单管理发货管理等 多类经营模式 多商 ...

  5. uniapp (H5、小程序、app)地图导航

    H5地图导航 腾讯地图 window.location.href = http://apis.map.qq.com/uri/v1/marker?marker=coord:lat,lng;addr:ad ...

  6. uniapp的打包:h5、微信小程序以及APP方式

    uniapp的打包:h5.微信小程序以及APP方式 H5打包 微信小程序打包 App打包 本人用的是HBuilder编译器,学习uniapp时b站某位大大推荐的,我刚开始接触代码时候也用过,那时候并不 ...

  7. 测试开发面试题目(三)——测试用例、安卓苹果系统区别、小程序与app的区别

    测试用例: 测试用例是指对一项特定的软件产品进行测试任务的描述.体现测试方案.方法.技术和策略.其内容包括测试目标.测试环境.输入数据.测试步骤.预期结果.测试脚本等,最终形成文档,简单的认为,测试用 ...

  8. 如何快速编写小程序商城和安卓 APP 商城

    本次 Chat 我将向大家介绍如何快速编写一款小程序商城和安卓 APP 商城.本次 Chat 适合对象:对移动开发有一定基础但又不会后台开发的群体.希望做一些实战项目练手的同学.不适合已经有丰富经验的 ...

  9. 微信小程序Android和ios授权,uni-app之APP和小程序微信授权方法

    uni-app 介绍 uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架. 适用平台:Android.iOS.微信小程序.实现了一套代码,同时发布到Android.iOS.微信小程序. ...

最新文章

  1. php nsdata,iOS播放PCM,NSData流代码(Audio Queue Services)
  2. linux python 图形界面开发_python在linux制作图形界面(snack)
  3. Python中超类是如何知道自己被继承的
  4. Algs4-1.3.45栈的可生成性
  5. mysql5.6开启binlog日志
  6. jQuery的创建对象,动态添加、修改、删除属性和方法
  7. 自动化运维之saltstack
  8. uCOS-II的学习笔记(共九期)和例子(共六个)
  9. 使用python Selenium实现智慧树界面化自动刷网课 chromehandless实现智慧树无界面化自动刷网课
  10. Xen调度分析-RT
  11. ROS 机器人操作系统:概述
  12. java生成随机数的代码_java生成随机数的代码
  13. Goonie企业竞争情报系统评为选中国优秀网络应用软件奖
  14. python 多线程 代理 爬取 豆果美食app
  15. IO流---基础 (附相对路径)
  16. 查询字符串中不含重复的最长子串
  17. 思科交换机冗余星形设计,附带sw1核心交换机配置
  18. 部分ADSL猫的默认密码
  19. 学习的目的:建立世界观、学以致用、知行合一
  20. 听说有人要买雅虎 这家公司还有值得让人花钱的地方吗

热门文章

  1. 微信小程序驾校教培服务系统+后台管理系统|前后分离VUE
  2. 俞敏洪微博经典语录:年轻人该如何恋爱
  3. c++windows+yolov5-6.2+openvino模型部署超详细
  4. 赋能 打造应对不确定性的敏捷团队 pdf_赋能——打造应对不确定的敏捷团队|《赋能》斯坦利...
  5. 饥荒机器人怎么解锁_饥荒机器人怎么玩 饥荒机器人详细玩法
  6. Linux---------安装以及基本语法知识
  7. FTP 基础配置,配置虚拟FTP账号
  8. 收音机c语言程序,基于51单片机的数字FM调频收音机的设计(附接线图,主程序代码)...
  9. 为什么网易和常州贝特康姆软件技术有限公司都声称是前cn99,他们之间是什么关系
  10. 人工智能轨道交通行业周刊-第2期(2022.6.13-6.19)