微信小程序之----语音录制功能

完整代码,请读者耐心看完

注意

  1. 首先创建录音对象
const recorderManager = wx.getRecorderManager()
const innerAudioContext = wx.createInnerAudioContext()
  1. 录音功能,授权与拒绝授权的逻辑处理
 wx.authorize({
      scope: 'scope.record',
      success() {
        that.stratRecordAudio()
      },
      fail() {
        wx.showModal({
          title: '提示',
          content: '您未授权录音,功能将无法使用',
          showCancel: true,
          confirmText: "授权",
          confirmColor: "#2D59DF",
          success: function (res) {
            if (res.confirm) {
              //确认则打开设置页面(重点)
              wx.openSetting({
                success: (res) => {
                  if (!res.authSetting['scope.record']) {
                    //未设置录音授权
                    wx.showModal({
                      title: '提示',
                      content: '您未授权录音,功能将无法使用',
                      showCancel: false,
                      success: function (res) {},
                    })
                  } else {
                    that.stratRecordAudio()
                  }
                },
                fail: function () {
                  console.log("授权设置录音失败");
                }
              })
            } else if (res.cancel) {
              console.log("cancel");
            }
          },
          fail: function () {
            console.log("openfail");
          }
        })
      }
    })
  1. 临时录音文件,要转存我们自己项目的资源站
// 传到资源保存站
wx.uploadFile({
      url: uploadAudio.uploadAudio,
      filePath: that.data.filePath,
      name: 'file',
      success(res) {
        filePath = JSON.parse(res.data).data[0]
        var params = {
          userId: that.data.userId,
          url: filePath,
          duration: that.data.duration,
          type: 2
        }
        //真正传到数据库
        postRecording(params).then(res => {
          wx.hideLoading()
          wx.showToast({
            title: '保存成功',
            icon: 'success',
            duration: 2000
          })
          wx.navigateTo({
            url: '/pages/card/package-1st/pages/card-change/cardChange?userId=' + that.data.userId,
          })
        })
      }
    })

wxss

page{
  background-color:#F3F3F7;
}
.editWrapBox {
  background-color: #ffffff;
  margin-bottom: 10px;
  overflow: hidden;
  position: relative;
}
.headerContentWrap{
  margin:0 auto;
  padding: 30px 0;
  box-sizing: border-box;

}
.headerInWrapItem{
  width:100vw;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}
.luyinWrap,.luyinWrap2,.luyinWrap3{
  width: 90px !important;
  height: 90px !important;
  line-height:75px  !important;
  border-radius: 50% !important;
  text-align: center !important;
  margin: 0;
}
.luyinWrap{
  background-color:#F1F3F8 !important;
}
.luyinWrap2{
  background-color:#2D59DF !important;
}
.luyinWrap3{
  background-color:#2D59DF;
  position: absolute;
  top: 25px;
}
.icon-maikefenghuatongyuyin{
  font-size: 35px;
  color: #2D59DF;
}
.icon{
  font-size: 35px;
  color: #ffffff;
}
.icon-bofanganniu,.icon-iconstop{
  font-size: 25px;
  color: #ffffff;
}
.actionName{
  margin-top: 14px;
  font-size: 14px;
  color: #333333;
}
.numberSize,.delText{
  color: #E50000;
}
.delText{
  font-size: 14px;
  width: 55px;
  height: 55px;
  text-align: center;
  line-height: 55px;
  margin-top: 27px;
  border: 1px solid #E50000;
  border-radius: 50%;
}
.progressWrap {
  width: 100vw;
  height: 40px;
  line-height: 40px;
  margin:0px auto;
  background-color: #BCCDFF;
  font-size: 14px;
  text-align: center;
  color: #333333;
}
.luyinOutWrap.active{
  background-color: #BCCDFF;
  opacity: 1;
  animation: scale 2.5s infinite ease alternate;
}
.luyinOutWrap{
  width:120px;
  height:120px;
  text-align: center;
  margin: 10px auto;
  border-radius: 50%;
}
@keyframes scale {
  0% {
    opacity:1
  }
  25% {
    opacity:0.75
  }
  45% {
    opacity:0.5
  }
  50% {
    opacity:0.25
  }
  75% {
    opacity:0.5
  }
  85% {
    opacity:0.75
  }
  100% {
    opacity:1
  }
  
}
.saveinfo {
  font-size: 16px !important;
  color: #ffff !important;
  text-align: center !important;
  background-color: #2D59DF !important;
  border-radius: 20px !important;
  width:95% !important;
  position: fixed !important;
  bottom: 10px !important;
  left: 10px !important;
}

wxml

<view class="editWrapBox">
  <!-- 未录音 -->
  <view class="headerContentWrap" wx:if="{{noRecordShow}}">
    <view class="headerInWrapItem">
      <button class="luyinWrap" bindtap="authorize"><i class="iconfont icon-maikefenghuatongyuyin"></i></button>
      <view class="actionName">点击录音</view>
    </view>
  </view>
  <!-- 录制语音中 -->
  <view wx:if="{{recordLuzhiShow}}">
    <view class="progressWrap">
      录音中(已录制<text class="numberSize">{{countNume}}s</text>),再次点击按钮即可停止录制
    </view>
    <view class="headerContentWrap">
      <view class="headerInWrapItem">
        <view class="luyinOutWrap active"></view>
        <button class="luyinWrap3" bindtap="stopRecordAudio"><i
            class="iconfont icon-maikefenghuatongyuyin icon"></i></button>
      </view>
    </view>
  </view>
  <!-- 播放语音中 -->
  <view wx:if="{{playAudioShow}}">
    <view class="progressWrap">
      播放中...
    </view>
    <view class="headerContentWrap">
      <view class="headerInWrapItem">
        <view class="luyinOutWrap active"></view>
        <button class="luyinWrap3"><i class="iconfont icon-iconstop"></i></button>
      </view>
    </view>
  </view>
  <!-- 录音完成 -->
  <view class="headerContentWrap" wx:if="{{finishRecordShow}}">
    <view class="headerInWrapItem">
      <view bindtap="playRecordAudio" data-type="1"> <button class="luyinWrap2"><i class="iconfont icon-bofanganniu"></i></button>
        <view class="actionName">点击播放录音1</view>
      </view>
      <view class="delText" bindtap="recycleRecordAudio">重录</view>
    </view>
  </view>
  <!--已经存在语音 -->
  <view class="headerContentWrap" wx:if="{{extistRecordShow}}">
    <view class="headerInWrapItem">
      <view bindtap="playRecordAudio" data-type="2"><button class="luyinWrap2"><i class="iconfont icon-bofanganniu"></i></button>
        <view class="actionName">点击播放录音2</view>
      </view>
      <view class="delText" bindtap="deleteRecord">删除</view>
    </view>
  </view>
  <!-- 保存按钮 -->
  <button class="saveinfo" wx:if="{{finishRecordShow}}" bindtap="saveRocordAudio">保存</button>
</view>

js

const recorderManager = wx.getRecorderManager()
const innerAudioContext = wx.createInnerAudioContext()
var init
==语音删除、保存接口== 
import {
  postRecording,
  deleteRecording
} from '../../../../../config/api/cardUrl'    
import {
  uploadAudio
} from '../../../../../config/basicConfig' //语音保存地址

Page({
  data: {
    noRecordShow: true, //初始显示
    recordLuzhiShow: false, //控制录制
    finishRecordShow: false, //完成录音
    extistRecordShow: false, //已存在录音
    playAudioShow: false, //播放按钮
    exisiFilePath: '', //已经存在的录音
    countNume: 0, // 倒计时
    filePath: '', // 临时语音录制文件
    duration: 0, // 录制时间
    userId: 0, //用户id
    id: 0, //语音id
  },
  onLoad: function (options) {
    this.setData({
      userId: parseInt(options.userId),
      id: parseInt(options.id)
    })
    if (options.filePath == "undefined") {
      this.setData({
        extistRecordShow: false,
        noRecordShow: true,
      })
    } else {
      this.setData({
        exisiFilePath: options.filePath,
        extistRecordShow: true,
        noRecordShow: false,
      })
    }
  },
  // 语音授权
  authorize() {
    var that = this
    wx.authorize({
      scope: 'scope.record',
      success() {
        that.stratRecordAudio()
      },
      fail() {
        wx.showModal({
          title: '提示',
          content: '您未授权录音,功能将无法使用',
          showCancel: true,
          confirmText: "授权",
          confirmColor: "#2D59DF",
          success: function (res) {
            if (res.confirm) {
              //确认则打开设置页面(重点)
              wx.openSetting({
                success: (res) => {
                  if (!res.authSetting['scope.record']) {
                    //未设置录音授权
                    wx.showModal({
                      title: '提示',
                      content: '您未授权录音,功能将无法使用',
                      showCancel: false,
                      success: function (res) {},
                    })
                  } else {
                    that.stratRecordAudio()
                  }
                },
                fail: function () {
                  console.log("授权设置录音失败");
                }
              })
            } else if (res.cancel) {
              console.log("cancel");
            }
          },
          fail: function () {
            console.log("openfail");
          }
        })
      }
    })
  },
  //录音计时器
  recordingTimer: function (time) {
    var that = this
    if (time == undefined) {
      //将计时器赋值给init
      init = setInterval(function () {
        var time = that.data.countNume + 1;
        that.setData({
          countNume: time
        })
      }, 1000);
    } else {
      clearInterval(init)
    }
  },
  // 开始录音
  stratRecordAudio() {
    clearInterval(init) //清除定时器
    // 监听音频开始事件
    this.setData({
      noRecordShow: false,
      recordLuzhiShow: true
    })
    recorderManager.onStart((res) => {})
    recorderManager.onStop((res) => {
      this.setData({
        recordLuzhiShow: false,
        finishRecordShow: true,
        filePath: res.tempFilePath,
        duration: res.duration
      })
      this.recordingTimer(this.data.countNume)
    })
    const options = {
      duration: this.data.duration, //指定录音的时长,单位 ms
      sampleRate: 16000, //采样率
      numberOfChannels: 1, //录音通道数
      encodeBitRate: 96000, //编码码率
      format: 'mp3', //音频格式,有效值 aac/mp3
      frameSize: 50, //指定帧大小,单位 KB
    }
    this.recordingTimer()
    recorderManager.start(options)
  },
  // 停止录音
  stopRecordAudio() {
    this.setData({
      recordLuzhiShow: false,
      finishRecordShow: true,
    })
    recorderManager.onStop((res) => {
      this.setData({
        filePath: res.tempFilePath,
        duration: res.duration
      })
    })
    this.recordingTimer(this.data.countNume)
    recorderManager.stop()
  },
  // 播放录音
  playRecordAudio(e) {
    //在ios下静音时播放没有声音,默认为true,改为false就好了。
    innerAudioContext.obeyMuteSwitch = false
    var filPathType = e.currentTarget.dataset.type
    if (filPathType == 1) {
      this.setData({
        playAudioShow: true,
        finishRecordShow: false
      })
      innerAudioContext.src = this.data.filePath
      innerAudioContext.play()
      innerAudioContext.onEnded(() => {
        this.setData({
          playAudioShow: false,
          finishRecordShow: true
        })
      })
    } else {
      this.setData({
        playAudioShow: true,
        extistRecordShow: false
      })
      innerAudioContext.src = this.data.exisiFilePath
      innerAudioContext.play()
      innerAudioContext.onEnded(() => {
        this.setData({
          playAudioShow: false,
          extistRecordShow: true
        })
      })
    }
   
  },

  // 重新录音
  recycleRecordAudio() {
    var that = this
    wx.showModal({
      title: "重新录音",
      content: "是否重新录制?",
      success(res) {
        if (res.confirm) {
          that.setData({
            noRecordShow: true, //初始显示
            recordLuzhiShow: false, //控制录制
            finishRecordShow: false, //完成录音
            extistRecordShow: false, //已存在录音
            playAudioShow: false, //播放按钮
            filePath: '',
            countNume: 0,
            duration: 0
          })
          innerAudioContext.stop()
        }
      }
    })
  },
  // 保存录音
  saveRocordAudio() {
    wx.showLoading({
      title: '保存中...',
    })
    var filePath = "",
      that = this
    wx.uploadFile({
      url: uploadAudio.uploadAudio,
      filePath: that.data.filePath,
      name: 'file',
      success(res) {
        filePath = JSON.parse(res.data).data[0]
        var params = {
          userId: that.data.userId,
          url: filePath,
          duration: that.data.duration,
          type: 2
        }
        postRecording(params).then(res => {
          wx.hideLoading()
          wx.showToast({
            title: '保存成功',
            icon: 'success',
            duration: 2000
          })
          wx.navigateTo({
            url: '/pages/card/package-1st/pages/card-change/cardChange?userId=' + that.data.userId,
          })
        })
      }
    })

  },
  // 删除语音
  deleteRecord() {
    var that = this
    wx.showModal({
      title: '提示',
      content: '确定要删除语音吗?',
      success(res) {
        if (res.confirm) {
          deleteRecording(that.data.id).then(res => {
            wx.showToast({
              title: '删除成功',
              icon: 'success',
              duration: 2000
            })
            wx.navigateTo({
              url: '/pages/card/package-1st/pages/card-change/cardChange?userId=' + that.data.userId,
            })
          })
        }
      }
    })
  },
})
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值