最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 小程序录音功能实现

    正文概述 掘金(爱喝华农学士的程序媛)   2021-03-07   621

    前言

    在开发小程序过程中,有一个实现录音功能并播放录音,将录音上传至服务器的需求。开发过程中使用了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被赋予值的时候,录音就会开始播放。

    总结

    以上就是整个录音功能和录音播放功能实现的整个流程,如有疑问欢迎大家一起交流。


    起源地下载网 » 小程序录音功能实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元