服务器之家:专注于服务器技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - js教程 - 小程序录音功能实现

小程序录音功能实现

2022-02-13 17:21爱喝华农学士的程序媛 js教程

这篇文章主要介绍了小程序录音功能实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

在开发小程序过程中,有一个实现录音功能并播放录音,将录音上传至服务器的需求。开发过程中使用了Taro框架,录音功能通过Taro.getRecorderManager()接口实现,上传录音至服务器通过Taro.uploadFile接口实现,播放录音使用Taro.createInnerAudioContext()接口实现。下面就详细介绍整个流程是如何实现的。

小程序录音

首先获取录音管理器模块:

?
1
const recorderManager = Taro.getRecorderManager();

在组件挂载完毕时注册录音监听事件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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函数的实现如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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用于停止录音。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = (app) => {
 const config = (exports = {});
 
 ...
 
 config.multipart = {
  mode: 'file',
  fileSize: '50mb',
 }
 ...
 
 return {
  ...config,
  ...userConfig,
 };
};

然后,在router.js中定义路由:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 提交录音
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写入具体实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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的上下文对象:

?
1
const innerAudioText = Taro.createInnerAudioContext();

和录音一样,在组件挂载完成时,注册监听事件:

?
1
2
3
4
5
6
7
8
9
10
useEffect(() => {
  innerAudioText.onPlay(() => {
   console.log('开始播放');
  });
 
  innerAudioText.onError((e) => {
   console.log('播放异常');
   console.log(e);
  });
 }, []);

在录音文件上传成功后,调用playAudio方法用于播放录音:

?
1
2
3
4
const playAudio = (url) => {
 innerAudioText.autoplay = true;
 innerAudioText.src = url;
};

在src被赋予值的时候,录音就会开始播放。

总结

到此这篇关于小程序录音功能实现的文章就介绍到这了,更多相关小程序 录音内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/6936718733767344136

延伸 · 阅读

精彩推荐
  • js教程JS实现简单抖动效果

    JS实现简单抖动效果

    这篇文章给大家结束了通过js实现抖动效果,非常不错,具有参考借鉴价值,感兴趣的朋友参考下吧...

    catEatBird9222022-01-12
  • js教程js简单粗暴的发布订阅示例代码

    js简单粗暴的发布订阅示例代码

    这篇文章主要给大家介绍了js简单粗暴的发布订阅的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    威威威威vvvv6452022-01-06
  • js教程js实现有趣的倒计时效果

    js实现有趣的倒计时效果

    这篇文章主要为大家详细介绍了js实现有趣的倒计时效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    搬砖大法4512022-01-04
  • js教程JavaScript中跨域问题的深入理解

    JavaScript中跨域问题的深入理解

    这篇文章主要给大家介绍了关于JavaScript中跨域问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    三七安6652022-02-10
  • js教程原生JS实现pc端轮播图效果

    原生JS实现pc端轮播图效果

    这篇文章主要为大家详细介绍了原生JS实现pc端轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    qq_1519846510192021-12-15
  • js教程JavaScript 中 find() 和 filter() 方法的区别

    JavaScript 中 find() 和 filter() 方法的区别

    JavaScript 在 ES6 上有很多数组方法,每种方法都有独特的用途和好处。...

    锋享前端4752021-12-28
  • js教程JavaScript 中的六种循环方法

    JavaScript 中的六种循环方法

    这篇文章主要介绍了JavaScript 中的六种循环方法,帮助大家更好的理解和使用JavaScript,感兴趣的朋友可以了解下...

    Saku8732021-12-27
  • js教程微信小程序tab切换可滑动切换导航栏跟随滚动实现代码

    微信小程序tab切换可滑动切换导航栏跟随滚动实现代码

    这篇文章主要介绍了微信小程序tab切换可滑动切换导航栏跟随滚动实现代码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...

    竹林中9252022-01-19