本文详解如何在微信小程序中利用wx.getRecorderManager实现录音功能,并通过wx.uploadFile将本地临时文件上传至服务器。后端采用Node.js的Express框架结合connect-multiparty中间件接收并处理上传的音频文件,解决临时文件自动删除问题,提供从前端录音到后端保存的完整代码示例与配置说明。
项目背景与需求概述
背景
在开发小程序的过程中,遇到了需要实现录音功能并将音频文件上传至服务器的需求。小程序端的录音功能通过调用微信提供的wx.getRecorderManager()方法创建实例来完成,录音生成的文件为本地临时文件。为了将这些文件上传到服务器,需使用微信的wx.uploadFile(Object object)方法,这构成了本项目的主要背景。
微信小程序端录音实现
小程序端
HTML页面主要包含两个按钮及相应的事件处理。第一个按钮用于播放录音,第二个按钮则绑定长按开始录音、松手停止录音的事件,用于控制录音过程。
<!--pages/record/record.wxml-->
<button bindtap="playVoice" type="primary" disabled="{{tempFilePath === ''}}">播放录音</button>
<button type="warn" bindtouchstart="beginRecord" bindtouchend="endRecord">长按开始录音,松手停止录音</button>
JavaScript代码主要涉及两个核心事件的处理逻辑,确保录音和播放功能的正常运行。
// pages/record/record.js
// 两个实例声明在Page之外,方便访问
const recorderManager = wx.getRecorderManager() //这是录音功能的实例,必须的
const innerAudioContext = wx.createInnerAudioContext(); //这是播放录音功能需要的实例
Page({
data: {
tempFilePath: '' //存放录音文件的临时路径
},
// 播放录音
playVoice: function(e) {
innerAudioContext.onPlay(() => {
console.log('开始播放')
})
innerAudioContext.onError((res) => {
console.log(res.errMsg)
console.log(res.errCode)
})
innerAudioContext.play();
},
// 录音
beginRecord:function(e) {
// 监听录音开始事件
recorderManager.onStart(() => {
console.log('recorder start')
})
// 监听已录制完指定帧大小的文件事件。如果设置了 frameSize,则会回调此事件。
recorderManager.onFrameRecorded((res) => {
const { frameBuffer } = res
console.log('frameBuffer.byteLength', frameBuffer.byteLength)
})
//录音的参数
const options = {
duration: 60000, //录音时间,默认是60s,提前松手会触发button的bindtouchend事件,执行停止函数并上传录音文件。超过60s不松手会如何并未测试过
sampleRate: 44100,
numberOfChannels: 1,
encodeBitRate: 192000,
format: 'mp3', //录音格式,这里是mp3
frameSize: 50 //指定帧大小,单位 KB。传入 frameSize 后,每录制指定帧大小的内容后,会回调录制的文件内容,不指定则不会回调。暂仅支持 mp3 格式。
}
//开始录音
recorderManager.start(options);
},
//停止录音并上传数据
endRecord:function(e) {
const self = this;
//停止录音
recorderManager.stop();
//监听录音停止事件,执行上传录音文件函数
recorderManager.onStop((res) => {
console.log('recorder stop', res)
//返回值res.tempFilePath是录音文件的临时路径 (本地路径)
self.setData({
tempFilePath: res.tempFilePath
})
innerAudioContext.src = res.tempFilePath
//上传录音文件
var uploadTask = wx.uploadFile({
//没有method,自动为POST请求
filePath: res.tempFilePath,
name: 'recordFile', //这个随便填
url: 'http://localhost:3000/record', //填写自己服务器的地址。
header: {
"Content-Type": "multipart/form-data" //必须是这个格式
},
success:(e) => {
console.log('succeed!');
console.log(e);
},
fail: (e) => {
console.log('failed!');
console.log(e);
}
});
uploadTask.onProgressUpdate((e) => {
console.log(e);
console.log('期望上传的总字节数:' + e.totalBytesExpectedToSend);
console.log('已经上传的字节数' + e.totalBytesSent);
})
})
}
})
至此,小程序前端的代码部分已经完成。
Node.js后端接收与处理
Node服务器端
前提条件:
后端服务选用Express框架搭建,若对Express不熟悉,建议先进行基础学习。要实现后端对用户上传文件的解析,必须配置合适的中间件,可参考文末关于Node.js使用connect-multiparty实现文件上传的讲解。项目初始化时需安装express和connect-multipparty依赖。
npm install express
npm install connnect-multiyparty
熟悉Node.js开发的读者应能理解上述步骤。此处省略--save参数,因为新版Node和npm会自动将依赖保存至package.json文件中。
//这是我的路由文件的代码片段,监听端口号3000等设置在我的另一个文件内。
//这只是代码片段,大概率跑不起来,只起一个demo的作用。如果需要完整的代码,可以留言给我。
const express = require('express');
const multiparty = require('connect-multiparty');
var router = express.Router();
var multipartMiddleware = multiparty();
router.use(multiparty({uploadDir:'./temp'})); //将接收文件的地址更改为当前目录下的temp文件夹。如果没有,则需要新建该文件夹。
// 处理录音文件
//只需要这样处理,上传的MP3文件就会保存在指定的目录下了。
router.post('/record', multipartMiddleware, (request, response) => {
console.log('received a request');
console.log(request.files);
request.on('end', () => {
response.send('通信完成');
})
})
重要提示:中间件保存的文件为临时文件,系统会在短时间内自动删除,因此必须及时处理这些文件,例如将其移动或写入到新文件中。
该框架已两年未更新,虽不一定是最佳选择,但在此场景下可行。
接下来介绍Node.js如何使用connect-multiparty实现文件上传的后端处理。
文件上传
文件上传是服务器常见功能。经过多次尝试不同的中间件,发现connect-multipparty在适配Node.js版本v0.12.11时较为简单且有效。
用法
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
app.post('/upload', multipartMiddleware, function(req, resp) {
console.log(req.body, req.files);
// don't forget to delete all req.files when done
});
前端以multipart/form-data格式上传数据,后端通过connect-multiparty中间件接收。需注意,接收结果req.files是一个对象,包含POST上传的参数及临时文件,文件通常位于/tmp目录下,需将其移动至指定存储位置。
var fs = require('fs');
var source = fs.createReadStream(path);
var dest = fs.createWriteStream(output);
source.pipe(dest);
source.on('end', function() { fs.unlinkSync(path);}); //delete
source.on('error', function(err) { });
参考
connect-multiparty
总结
关于微信小程序录音实现并上传至Node.js服务器解析接收的内容介绍至此。更多相关微信小程序录音上传内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!