微信小程序:录音功能(授权、统计时长、上传)

最近呢,用小程序做了个录音的功能,接下来呢,与大家一起分享一下我的开发心得,希望能帮到大家。那我们就继续向下👇看吧~

需求呢,差不多是这样的:
1.单击开始录制(不是摁住不放哦)
2.点击完成上传录音
3.录音计时功能
4.当到达360s,自动进行上传

好了那来看看效果图吧,如下图所示:

录音.gif

接下来,进入主题,奥利给
一开始呢,打算用wx.startRecord(),后来看了下文档,发现从基础库 1.6.0 开始,本接口停止维护,被 wx.getRecorderManager 代替了,下面的我会说一下录音的几个重点功能,那我们继续向下走👇

1. data数据

data: {
    recorderManager: null,
    curTime: 0,
    recorder: {
      status: 'ready', // 'ready' | 'recording'
      text: '点击录制',
    },
    timer: null,
    secondes: 0,
    startTimestamp: 0,
    isupload: false
},

2.点击录制与停止

recordBtn: throttle(function () {
      let { status } = this.data.recorder;
      if(!this.data.isupload){
        if (status === 'ready') {
          this.getRecordLimit()
        } else if (status === 'recording') {
          this._endRecord()
        }
      }
 }, 1000),

3.开始录音

_startRecord() {
      this.data.startTimestamp = Date.now();
      const options = {
        duration: 600000,//指定录音的时长,单位 ms,最大为10分钟(600000),默认为1分钟(60000)
        sampleRate: 16000,//采样率
        numberOfChannels: 1,//录音通道数
        encodeBitRate: 96000,//编码码率
        format: 'mp3',//音频格式,有效值 aac/mp3
        frameSize: 50,//指定帧大小,单位 KB
      }
    
      //点击录制
      this.data.recorderManager.start(options);

      //开始录音计时
      this.countDown();

      this.data.recorderManager.onStart(() => {
        console.log('点击录制...')
      })

      //错误回调
      this.data.recorderManager.onError((res) => {
        console.log('录音失败', res);
      })
    },

4.停止录音

_endRecord() {
      clearInterval(this.data.timer);
      this.data.recorderManager.stop();
      this.data.recorderManager.onStop((res) => {
        console.log('停止录音', res)
        let filePath = res.tempFilePath;
        let duration = res.duration;
        if((Date.now() - this.data.startTimestamp) / 1000 < 2) {
          wx.showToast({
            title: '录音时间太短!',
            icon: 'none',
            duration: 1500
          }
          return;
        }
        this._uploadRecord(filePath, duration)
      })
 },

5.上传录音

export const ossUploadFile = (fileUrl) => {
    return new Promise((resolve, reject) => {
        //获取阿里云oss上传相关凭证
        getOssToken('audio/')
        .then(res => {
          let ossPolicy = res.data;
          let fileKey = getAudioFileKey();
          wx.uploadFile({
            url: '需要将录音上传到的域名' 
            filePath: fileUrl, // onStop之后生成的tempFilePath
            name: 'file', 
            formData: {
              'key': 'audio/' + fileKey,
              'policy': ossPolicy.policy,
              'OSSAccessKeyId': ossPolicy.accessId,
              'signature': ossPolicy.signature,
              "success_action_status": 200
            },
            success() {
                resolve(OSS_HOST + "/audio/" + fileKey)
            },
            fail(err) {
                reject('upload fail => ', err)
            }
          })
        })
        .catch(err => {
            reject('getOssTokenFail => ', err)
        })
    })
}

6.录音授权

getRecordLimit() {
      let that = this;
      wx.getSetting({
        success(res) {
          if (!res.authSetting['scope.record']) { // 未授权
            wx.authorize({
              scope: 'scope.record',
              success () { // 一次才成功授权
                that._startRecord()
              },
              fail(err) {
                console.log(err)
                wx.showModal({
                  title: '温馨提示',
                  content: '您未授权录音,该功能将无法使用',
                  showCancel: true,
                  confirmText: "授权",
                  success: function (res) {
                    if (res.confirm) {
                      wx.openSetting({
                        success: (res) => {
                          if (!res.authSetting['scope.record']) {
                            //未设置录音授权
                            wx.showModal({
                              title: '提示',
                              content: '您未授权录音,功能将无法使用',
                              showCancel: false,
                              success: function () {}
                            })
                          } else { // 二次才成功授权
                            that._startRecord()
                          }
                        },
                        fail: function () {
                          console.log("授权设置录音失败");
                        }
                      })
                    }
                  },
                  fail: function (err) {
                    console.log("打开录音弹框失败 => ", err);
                  }
                })
              }
            })
          } else { // 已授权
            that._startRecord()
          }
        }
      })
    },

7.统计时长(包括自动停止录音,并上传录音)

countDown() {
   this.data.timer = setInterval(() => {
      this.data.secondes++;
      if (this.data.secondes > 360) {
          clearInterval(this.data.timer);
          this.data.recorderManager.stop();
          this.data.recorderManager.onStop((res) => {
              console.log('时辰已到,自动跳转')
              let filePath = res.tempFilePath;
              let duration = 360000;
              this._uploadRecord(filePath, duration)
           })
           return;
       }
       this.setData({
            curTime: this.data.secondes
       });
   }, 1000);
}

8.录音动画

这一块呢主要是运用帧动画写的,大家可以参考一下哦~

<view class="recode">
     <view class="record-wave-multiple">
         <view></view>
         <view></view>
         <view></view>
     </view>
     <view class="record-bgm"></view>
 </view>

.recode {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 120rpx;
    height: 120rpx;
    border-radius: 50%;
    color: #fff;
}
.recode .record-bgm {
    width: 105rpx;
    height: 105rpx;
    border-radius: 50%;
    background:rgba(105,129,255,1);
}
.recode .record-wave-multiple {
    position: absolute;
    left: 0; 
    top: 0;
}
.record-wave-multiple>view {
    display: inline-block;
    background-color: #6981FF;
    border: 0 solid #6981FF;
    position: absolute;
    top: -25rpx;
    left: -27rpx;
    width: 170rpx;
    height: 170rpx;
    border-radius: 100%;
    opacity: 0;
    -webkit-animation: circle-wave-multiple 1.8s cubic-bezier(.41,.4,.67,1) 0s infinite;
    animation: circle-wave-multiple 1.8s cubic-bezier(.41,.4,.67,1) 0s infinite;
}
.record-wave-multiple>view:nth-child(2) {
    -webkit-animation-delay: .6s;
    animation-delay: .6s;
}
.record-wave-multiple>view:nth-child(3) {
    -webkit-animation-delay: 1.2s;
    animation-delay: 1.2s;
}
@keyframes circle-wave-multiple {
    0% {
        opacity: 0;
        transform: scale(.4);
    }
    5% {
        opacity: .5;
    }
    100% {
        opacity: 0;
        transform: scale(1);
    }
} 

下面呢,给大家说一下几个注意事项:⚠️
1.在执行stop();的时候,记得在后面加上 onStop和onError,不然它会自动去找你有onStop或者有onError 的地方,如果需要共用的话不写也行,当然这是看情况的哦,一定切记!!!
2.在开发者工具上呢,会录不进去音,不过在真机上是没问题的

到此呢,咱的录音功能也就写的差不多了,如果说小编的代码有什么问题,或者需要优化的地方呢,或者需要帮助,欢迎在下方评论区留言,小编会第一时间出现在大家面前~

最后呢,祝大家每天开开心心,快快乐乐,让bug离地我们远远的,永远都不要出现,哈哈哈😁~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260