前言
在开发小程序过程中,有一个实现录音功能并播放录音,将录音上传至服务器的需求。开发过程中使用了Taro框架,录音功能通过Taro.getRecorderManager()接口实现,上传录音至服务器通过Taro.uploadFile接口实现,播放录音使用Taro.createInnerAudioContext()接口实现。下面就详细介绍整个流程是如何实现的。
小程序录音
首先获取录音管理器模块:
const recorderManager = Taro.getRecorderManager();
在组件挂载完毕时注册录音监听事件:
useEffect(() => { // 监听录音开始 recorderManager.onStart(() => { console.log('开始录音'); }); // 监听录音暂停 recorderManager.onPause(() => { console.log('暂停录音'); }); // 监听录音继续 recorderManager.onResume(() => { console.log('继续录音'); }); // 监听录音停止 recorderManager.onStop((res) => { if (res.duration < 1000) { Taro.showToast({ title: '录音时间太短', duration: 1000, icon: 'none', }); } else { console.log('停止录音'); fileUpload(res.tempFilePath); } }); recorderManager.onError(() => { Taro.showToast({ title: '录音失败!', duration: 1000, icon: 'none', }); }); }, []);
在录音onStop的回调函数中,我们可以获取到录音的临时地址res.tempFilePath,但这个地址是有有效期限的,所以我们需要将这个录音上传至服务器后台,进行保存,后续才能正常使用。
onStop回调函数中我们调用了fileUpload函数实现文件上传,fileUpload函数的实现如下:
const fileUpload = (tempFilePath) => { Taro.uploadFile({ url: 'http://127.0.0.1:7001/record', // 服务器地址 filePath: tempFilePath, name: 'file', // 这个随便填 header: { 'content-type': 'multipart/form-data', // 格式必须是这个 Authorization: Taro.getStorageSync('token'), }, // formData用于传输除文件以外的一些信息 formData: { record_name: '朗诵作品', poem_id: poemInfo.id, category: poemInfo.category, }, success: (res) => { console.log(res); const url = res.data; playAudio(url); // 播放录音 }, fail: (error) => { console.log('failed!'); console.error(error); }, }); };
需要注意的点是:header中的content-type必须是multipart/form-data。
录音事件的处理
第一次点击handleClick就会触发开始录音,之后会通过当前状态判断是暂停录音还是继续录音。handleComplete用于停止录音。
const handleClick = () => { const curPause = pause; setPause(!curPause); if (firstRecord) { setfirstRecord(false); recorderManager.start({ duration: 60000, sampleRate: 44100, numberOfChannels: 1, encodeBitRate: 192000, format: 'mp3', frameSize: 50, }); Taro.showToast({ title: '开始录音', duration: 1000, icon: 'none', }); } else { if (curPause) { recorderManager.pause(); // 暂停录音 } else { recorderManager.resume(); // 继续录音 } } }; const handleComplete = () => { recorderManager.stop(); // 停止录音 };
后台实现录音存储并返回录音地址
网上大多数博客都没有涉及这块内容,下面就介绍一下如何实现,后台框架我用的是阿里的egg.js。
文件上传需要配置的东西可见官方文档:egg.js文件上传。我们这里使用它的第一种File模式来实现。
因为egg.js框架内置了Multipart插件,可以解析上传的multipart/form-data类型的数据。
首先,现在配置文件config.default.js中写入multipart配置:
module.exports = (app) => { const config = (exports = {}); ... config.multipart = { mode: 'file', fileSize: '50mb', } ... return { ...config, ...userConfig, }; };
然后,在router.js中定义路由:
// 提交录音 router.post('/record', auth, controller.record.postRecord); 在controller目录下定义record.js文件写入如下内容: const Controller = require('egg').Controller; class RecordController extends Controller { async postRecord() { const { ctx } = this; const file = ctx.request.files[0]; const { record_name, poem_id, category } = ctx.request.body; const res = await ctx.service.record.postRecord(file, record_name, poem_id, category); ctx.body = res; } } module.exports = RecordController;
在service目录下定义record.js写入具体实现:
const Service = require('egg').Service; let OSS = require('ali-oss'); let aliInfo = { // https://help.aliyun.com/document_detail/31837.html region: 'oss-cn-guangzhou', bucket: 'poem-mini-program', accessKeyId: 'xxx', // 填入阿里云的accessKeyId accessKeySecret: 'xxx', // 填入阿里云的accessKeySecret }; let client = new OSS(aliInfo); class RecordService extends Service { async postRecord(file, record_name, poem_id, category) { const url = await this.uploadOSS(file); await this.updateRecord(url, record_name, poem_id, category); return url; } async uploadOSS(file) { const { ctx } = this; let result; try { // 处理文件,比如上传到云端 result = await client.put(file.filename, file.filepath); } finally { // 需要删除临时文件 await ctx.cleanupRequestFiles(); } return result.url; } async updateRecord(url, record_name, poem_id, category) { const { ctx } = this; console.log('从ctx.locals中取openid'); console.log(ctx.locals.openid); const openid = ctx.locals.openid; // 将用户信息记录到数据库中 const res = await ctx.model.Record.create({ record_name: record_name, record_url: url, poem_id: poem_id, category: category, openid: openid, }); } } module.exports = RecordService;
这里需要注意的是:
- 需要注册阿里云账号,并在对象存储那里新建一个存储桶用于存放音频,也就是云存储的实现。
- 需要安装ali-ossnpm包,用于连接阿里云对象存储。在后台接收到前端上传的临时文件后,就会将音频上传至阿里云对象存储中(client.put)。
播放录音
细心的小伙伴可以注意到在使用Taro.uploadFile接口上传录音后,在success回调中调用了playAudio函数用于播放音频,接下来讲一下播放音频是如何实现的。
首先,使用Taro.createInnerAudioContext获取audio的上下文对象:
const innerAudioText = Taro.createInnerAudioContext();
和录音一样,在组件挂载完成时,注册监听事件:
useEffect(() => { innerAudioText.onPlay(() => { console.log('开始播放'); }); innerAudioText.onError((e) => { console.log('播放异常'); console.log(e); }); }, []);
在录音文件上传成功后,调用playAudio方法用于播放录音:
const playAudio = (url) => { innerAudioText.autoplay = true; innerAudioText.src = url; };
在src被赋予值的时候,录音就会开始播放。
总结
到此这篇关于小程序录音功能实现的文章就介绍到这了,更多相关小程序 录音内容请搜索NICE源码以前的文章或继续浏览下面的相关文章希望大家以后多多支持NICE源码!