【简单的录音例子,复制过去就可用】
使用了uni组件和uView组件;
uniapp小程序授权录音并录制后保存到java后端。
直接复制过去粘贴到.vue文件即可测试;官方的回调有时候无效,所以有些地方注释了。
<template>
<view class="container">
<u-popup :show="showForm" mode="bottom" closeable="true" @close="closeForm" @open="openForm"
:customStyle="{'border-radius': '20px 20px 0px 0px'}">
<view style="padding: 50px 20px 40px 20px;height: 600rpx;overflow: auto;">
<uni-section title="录音并上传" type="line" padding>
<view style="margin-bottom: 100px;">
<view style="margin-bottom: 20px;">
<view>
<text>剩余时间:{{tempCount}}text>
<text style="margin-left: 10px;">已录时间:{{voiceCount}}text>
view>
view>
<u-button v-if="startState == 0" :text="btn_start_text" type="success" size="normal"
@click="startRecord()">u-button>
<u-button v-if="startState == 1" :text="btn_pr_text" type="success" size="normal"
@click="pauseResumeRecord()">u-button>
<u-button v-if="startState == 1" text="停止录音" type="warning" size="normal" @click="stopRecord()">
u-button>
view>
<u-button text="提交" type="primary" size="normal" @click="submitFile()">u-button>
uni-section>
view>
u-popup>
view>
template>
<script>
const recorderManager = uni.getRecorderManager(); // 录音实例对象
export default {
data() {
return {
btn_start_text: '开始录音', // 开始录制/重新录制按钮
btn_pr_text: '暂停录音', // 暂停/继续按钮
showForm: true, // 显示弹框表单
voicePath: '', // 录音文件临时地址
tempInter: null, // 计时器
tempCount: '00:00', // 倒计时
tempVoice: false, // 是否暂停或者结束
startState: 0, // 0未开始录音 1开始录音
voiceNum: 120, // 录制倒计时,2分钟
voiceCount: '00:00', // 已录制时间
}
},
onLoad() {
//this.creatRecorder();
},
methods: {
/**
* 录音实例-初始化
*/
creatRecorder() {
let self = this;
self.countInter(self.voiceNum); // 2分钟
self.tempVoice = true;
self.startState = 1;
self.voicePath = '';
// 录音开始(有时候失效)
recorderManager.onStart(function() {
// console.log('开始录音');
// self.countInter(120); // 2分钟
// self.tempVoice = true;
// self.startState = 1;
// self.voicePath = '';
});
// 录音暂停(有时候失效)
recorderManager.onPause(function() {
// console.log('暂停录音');
// self.tempVoice = false;
// self.btn_pr_text = '继续录音';
});
// 录音继续(有时候失效)
recorderManager.onResume(function() {
// console.log('继续录音');
// self.tempVoice = true;
// self.btn_pr_text = '暂停录音';
});
// 录音停止
recorderManager.onStop(function(res) {
console.log('停止录音', res);
self.voicePath = res.tempFilePath;
self.tempVoice = false;
self.btn_pr_text = '暂停录音';
self.btn_start_text = '重新录制';
self.startState = 0;
clearInterval(self.tempInter);
});
// 录音错误
recorderManager.onError(function(errMsg) {
console.log('录音错误', errMsg);
});
},
/**
* 开始录音
*/
startRecord() {
let self = this;
uni.authorize({
scope: 'scope.record',
success() {
recorderManager.start({
duration: 60000 * 2 // 2分钟
});
self.creatRecorder();
},
fail() {
uni.showModal({
content: '检测到您没打开录音功能权限,是否去设置打开?',
confirmText: "确认",
cancelText: '取消',
success(res) {
uni.openSetting({
success(res) {
console.log(res);
},
fail(res) {
uni.showToast({
title: '打开授权设置失败',
icon: 'none'
})
}
});
}
})
}
})
},
/**
* 暂停/继续
*/
pauseResumeRecord() {
let self = this;
if (this.btn_pr_text == '暂停录音') {
recorderManager.pause();
console.log('暂停录音');
self.tempVoice = false;
self.btn_pr_text = '继续录音';
} else {
recorderManager.resume();
console.log('继续录音');
self.tempVoice = true;
self.btn_pr_text = '暂停录音';
}
},
/**
* 停止录音
*/
stopRecord() {
let self = this;
recorderManager.stop();
self.tempVoice = false;
self.btn_pr_text = '暂停录音';
self.btn_start_text = '重新录制';
self.startState = 0;
clearInterval(self.tempInter);
},
/**
* 录音倒计时
* @param {Object} val
*/
countInter(val) {
let self = this;
let count = Number(val);
self.formatTime(count);
self.tempInter = setInterval(() => {
if (self.tempVoice && count > 0) {
count--;
self.tempCount = self.formatTime(count);
self.voiceCount = self.formatTime(self.voiceNum - count);
} else if (self.tempVoice) {
clearInterval(self.tempInter);
}
}, 1000)
},
/**
* 格式化时间格式
* @param {Object} num
*/
formatTime(num) {
num = num.toFixed(0);
let second = num % 60;
second = (second < 10) ? '0' + second : second;
let min = Math.floor(num / 60);
min = (min < 10) ? '0' + min : min;
return min + ":" + second;
},
// 表单-打开(回调)
openForm() {},
// 表单-关闭(回调)
closeForm() {
this.showForm = false;
clearInterval(this.tempInter);
this.tempVoice = false;
},
// 表单-提交
submitFile() {
let self = this;
if (!this.voicePath) {
uni.showToast({
title: '请录制后再提交',
icon: 'none'
})
return;
}
uni.showLoading({
title: '提交中'
});
uni.uploadFile({
url: this.jsAjax.api + '/upload/applet/voice', // 自己后台接收的接口
filePath: this.voicePath,
name: 'file',
formData: {},
success: (res) => {
uni.hideLoading();
uni.showToast({
title: '上传成功',
icon: 'none'
})
//self.showForm = false;
// 重置清空数据
self.voicePath = '';
self.tempVoice = false;
self.btn_pr_text = '暂停录音';
self.btn_start_text = '开始录音';
self.startState = 0;
self.tempCount = self.formatTime(0);
var obj = JSON.parse(res.data);
console.log(obj);
},
fail: (err) => {
uni.hideLoading();
uni.showToast({
title: '上传失败',
icon: 'none'
})
}
});
},
},
}
script>
<style>
page {
background-color: #fff !important;
}
.container {
padding: 10px 15px;
}
button {
margin-bottom: 10px;
}
style>
在startRecord()方法中已经体现,如果检测到没有授权麦克风,就弹到设置中需要用户手动开启
参考官网:https://uniapp.dcloud.net.cn/api/other/setting.html#opensetting
/**
* 临时文件存储(小程序)
*
* @param request
* @return
*/
@RequestMapping(value = "/applet/voice")
@ResponseBody
public Result voiceSave(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request) {
try {
// 是本地存储,或指定目录存储
String path = (serverType == 1) ? NGINXPATH : request.getServletContext().getRealPath("");
String yName = multipartFile.getOriginalFilename();
String hz = yName.substring(yName.lastIndexOf("."));//获取文件后缀
String fileName = System.currentTimeMillis() + hz;
String filepath = "upload/tem/"+ fileName;
File file = new File(path + filepath);
if (!file.exists()) {
file.mkdirs();
}
multipartFile.transferTo(file);
return Result.success(filepath, "上传成功");
}catch (Exception e){
return Result.error("文件上传异常");
}
}
参考官网:https://uniapp.dcloud.net.cn/api/media/record-manager.html
音频播放:https://blog.csdn.net/weixin_43992507/article/details/129861379