前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小程序录音功能实现

小程序录音功能实现

原创
作者头像
IT工作者
修改2022-02-17 20:30:59
3.4K0
修改2022-02-17 20:30:59
举报
文章被收录于专栏:程序技术知识

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

小程序录音

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

代码语言:javascript
复制
const recorderManager = Taro.getRecorderManager();

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

代码语言:javascript
复制
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函数的实现如下:

代码语言:javascript
复制
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用于停止录音。

代码语言:javascript
复制
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配置:

代码语言:javascript
复制
module.exports = (app) => {
  const config = (exports = {});
  
  ...

  config.multipart = {
    mode: 'file',
    fileSize: '50mb',
  }
  ...

  return {
    ...config,
    ...userConfig,
  };
};

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

代码语言:javascript
复制
// 提交录音
router.post('/record', auth, controller.record.postRecord);

controller目录下定义record.js文件写入如下内容:

代码语言:javascript
复制
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写入具体实现:

代码语言:javascript
复制
const Service = require('egg').Service;
let OSS = require('ali-oss');

let aliInfo = {
  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-oss npm包,用于连接云对象存储。在后台接收到前端上传的临时文件后,就会将音频上传至云对象存储中(client.put)。

播放录音

细心的小伙伴可以注意到在使用Taro.uploadFile接口上传录音后,在success回调中调用了playAudio函数用于播放音频,接下来讲一下播放音频是如何实现的。

首先,使用Taro.createInnerAudioContext获取audio的上下文对象:

代码语言:javascript
复制
const innerAudioText = Taro.createInnerAudioContext();

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

代码语言:javascript
复制
useEffect(() => {
    innerAudioText.onPlay(() => {
      console.log('开始播放');
    });

    innerAudioText.onError((e) => {
      console.log('播放异常');
      console.log(e);
    });
  }, []);

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

代码语言:javascript
复制
const playAudio = (url) => {
  innerAudioText.autoplay = true;
  innerAudioText.src = url;
};

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 小程序录音
  • 录音事件的处理
  • 后台实现录音存储并返回录音地址
  • 播放录音
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档