前言
微信小程序中可以实现录音的主要有wx.startRecord()和wx.getRecorderManager(),其中wx.startRecord()从微信开发者工具基础库1.6后停止维护,开始启用更加强大的wx.getRecorderManager()。
一、关于wx.startRecord()的坑
wx.startRecord()使用还是相当容易的,微信官方示例便是使用wx.startRecord()。
1 wx.startRecord({
2 success(res) {
3 const tempFilePath = res.tempFilePath
4 console.log(res)
5 }
6 })
7 setTimeout(function () {
8 wx.stopRecord() // 结束录音
9 }, 3000)
成功录音的返回值为一个含有音频临时路径的对象
1 errMsg: "startRecord:ok"
2 tempFilePath: "http://tmp/wx88e053d45b28e2cf.o6zAJs-nrru-YZpqRQeb-X8EzBfk.JVhmiR78K4oY2e7522995230f041a81c5967a4e1598c.silk"
这个silk格式为加密格式,在真机上可以播放,上传到服务器以后,其它用户无法播放,只有上传者可以播放。
如果要分享给别人,得先解密,再转换为其它格式,网上的教程很多,但是比较麻烦
二、关于wx.getRecorderManager()的实战解析
有一个项目,需要使用录音,上传到云存储后,分享给其它人。
1 const recorderManager = wx.getRecorderManager()
2 const backgroundAudio = wx.getBackgroundAudioManager()
3 var util = require('../../utils/util.js');
4 Page({
5 data: {
6 openRecordingdis: "block", //显示录机图标
7 shutRecordingdis: "none", //隐藏停止图标
8 recordingTimeqwe: 0, //录音计时
9 setInter: "", //录音名称
10 soundUrl: ""
11 },
12
13 //录音计时器
14 recordingTimer: function() {
15 var that = this;
16 //将计时器赋值给setInter
17 that.data.setInter = setInterval(
18 function() {
19 var time = that.data.recordingTimeqwe + 1;
20 that.setData({
21 recordingTimeqwe: time
22 })
23 }, 1000);
24 },
25
26
27 //开始录音
28 openRecording: function() {
29 var that = this;
30 wx.getSystemInfo({
31 success: function(res) {
32 that.setData({
33 shutRecordingdis: "block",
34 openRecordingdis: "none"
35 })
36 }
37 })
38 const options = {
39 duration: 60000, //指定录音的时长,单位 ms,最大为10分钟(600000),默认为1分钟(60000)
40 sampleRate: 16000, //采样率
41 numberOfChannels: 1, //录音通道数
42 encodeBitRate: 96000, //编码码率
43 format: 'mp3', //音频格式,有效值 aac/mp3
44 frameSize: 50, //指定帧大小,单位 KB
45 }
46 //开始录音计时
47 that.recordingTimer();
48 //开始录音
49 recorderManager.start(options);
50 recorderManager.onStart(() => {
51 console.log('。。。开始录音。。。')
52 });
53 //错误回调
54 recorderManager.onError((res) => {
55 console.log(res);
56 })
57 },
58
59 //结束录音
60 shutRecording: function() {
61 var that = this;
62 wx.getSystemInfo({
63 success: function(res) {
64 that.setData({
65 shutRecordingdis: "none",
66 openRecordingdis: "block"
67 })
68 }
69 })
70 recorderManager.stop();
71 recorderManager.onStop((res) => {
72 const that = this
73 let timestamp = util.formatTime2(new Date());
74 console.log('。。停止录音。。', res.tempFilePath)
75 const {
76 tempFilePath
77 } = res;
78 //结束录音计时
79 clearInterval(that.data.setInter);
80 wx.cloud.uploadFile({
81 cloudPath: "sounds/"+timestamp + '-' + this.randomNum(10000, 99999) + '.mp3',
82 filePath: tempFilePath,
83 // 成功回调
84 success: res => {
85 console.log('上传成功', res)
86 that.setData({
87 soundUrl: res.fileID,
88 // time: util.formatTime1(new Date())
89 })
90 },
91 })
92
93 })
94 },
95
96 //录音播放
97 recordingAndPlaying: function(eve) {
98
99 // console.log(eve)
100 var tempsound = eve.currentTarget.dataset.soundid
101 tempsound = "https://6e65-newdj-d79af2-1257790921.tcb.qcloud.la/sounds"+this.midstr(tempsound)
102 // console.log(tempsound)
103 wx.playBackgroundAudio({
104 //播放地址
105 dataUrl: tempsound
106 })
107 },
108
109 //生成从minNum到maxNum的随机数
110 randomNum(minNum, maxNum) {
111 switch (arguments.length) {
112 case 1:
113 return parseInt(Math.random() * minNum + 1, 10);
114 break;
115 case 2:
116 return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
117 break;
118 default:
119 return 0;
120 break;
121 }
122 },
123 midstr(str) {
124 var strnum = str.lastIndexOf('/')
125 var ministr = str.substr(strnum)
126 return ministr
127 },
128 })
1.首先声明录音组件
const recorderManager = wx.getRecorderManager()
2. 开始录音的实现
1 //开始录音
2 openRecording: function() {
3 var that = this;
4 wx.getSystemInfo({
5 success: function(res) {
6 that.setData({
7 shutRecordingdis: "block",
8 openRecordingdis: "none"
9 })
10 }
11 })
12 const options = {
13 duration: 60000, //指定录音的时长,单位 ms,最大为10分钟(600000),默认为1分钟(60000)
14 sampleRate: 16000, //采样率
15 numberOfChannels: 1, //录音通道数
16 encodeBitRate: 96000, //编码码率
17 format: 'mp3', //音频格式,有效值 aac/mp3
18 frameSize: 50, //指定帧大小,单位 KB
19 }
20 //开始录音计时
21 that.recordingTimer();
22 //开始录音
23 recorderManager.start(options);
24 recorderManager.onStart(() => {
25 console.log('。。。开始录音。。。')
26 });
27 //错误回调
28 recorderManager.onError((res) => {
29 console.log(res);
30 })
31 },
3. 结束录音的实现
1 //结束录音
2 shutRecording: function() {
3 var that = this;
4 wx.getSystemInfo({
5 success: function(res) {
6 that.setData({
7 shutRecordingdis: "none",
8 openRecordingdis: "block"
9 })
10 }
11 })
12 recorderManager.stop();
13 recorderManager.onStop((res) => {
14 const that = this
15 let timestamp = util.formatTime2(new Date());
16 console.log('。。停止录音。。', res.tempFilePath)
17 const {
18 tempFilePath
19 } = res;
20 //结束录音计时
21 clearInterval(that.data.setInter);
22 wx.cloud.uploadFile({
23 cloudPath: "sounds/"+timestamp + '-' + this.randomNum(10000, 99999) + '.mp3',
24 filePath: tempFilePath,
25 // 成功回调
26 success: res => {
27 console.log('上传成功', res)
28 that.setData({
29 soundUrl: res.fileID,
30 // time: util.formatTime1(new Date())
31 })
32 },
33 })
34 })
35 },
第13行,录音停止后,生成mp3格式的临时文件,以jason格式提示,包含时长,文件大小和临时文件名
1 {
2 duration: 2532
3 fileSize: 42268
4 tempFilePath: "http://tmp/wx88e053d45b28e2cf.o6zAJs-nrru-YZpqRQeb-X8EzBfk.73z3a3qIwC7yc13f32e3d179133ac77ca7851ec7d25b.durationTime=2532.mp3"
5 }
第15行,生成一个时间戳,用来生成文件名,
第22行,上传至云存储,为了避免出现同时有多个进程上传的极端情况,加了一个5位数的随机数,
第29行,上传成功后,将生成的云文件ID返给data变量soundUrl
1 {
2 errMsg: "cloud.uploadFile:ok"
3 fileID: "cloud://newdj-d79af2.6e65-newdj-d79af2-1257790921/sounds/20190731162324-40454.mp3"
4 }
4.播放云存储里的录音
1 //录音播放
2 recordingAndPlaying: function(eve) {
3 // console.log(eve)
4 var tempsound = eve.currentTarget.dataset.soundid
5 tempsound = "https://6e65-newdj-d79af2-1257790921.tcb.qcloud.la/sounds" + this.midstr(tempsound)
6 // console.log(tempsound)
7 wx.playBackgroundAudio({
8 //播放地址
9 dataUrl: tempsound
10 })
11 },
点击播放按钮时,把录音的云文件名传递到JS
1 <view bindtap='recordingAndPlaying' data-soundid="{{soundUrl}}">
2 <image class="progress_img" src='/images/play.png'></image>
3 </view>
data-soundid--->eve.currentTarget.dataset.soundid
然后第5行,将云文件名,转换为可供真机使用的https文件,midstr(tempsound)函数是取"/"之后的文件名,
"https://6e65-newdj-d79af2-1257790921.tcb.qcloud.la/sounds",为本项目所使用云开发环境所对应的路径
将"cloud://newdj-d79af2.6e65-newdj-d79af2-1257790921/sounds"替换后即可使用。 注意标黑部分,通过对两个路径的比对,可以找到cloud://转https://的规律:
"cloud://云环境ID."===>"https://",之后再加上".tcb.qcloud.la"即可
5.生成随机数的通用函数
1 //生成从minNum到maxNum的随机数
2 randomNum(minNum, maxNum) {
3 switch (arguments.length) {
4 case 1:
5 return parseInt(Math.random() * minNum + 1, 10);
6 break;
7 case 2:
8 return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
9 break;
10 default:
11 return 0;
12 break;
13 }
14 },
6.取"/"右侧的字符串
midstr(str) {
var strnum = str.lastIndexOf('/')
var ministr = str.substr(strnum)
return ministr
},
三、WXML的实现
1 <view class='progress_box' bindtap='openRecording' style="display:{{openRecordingdis}}">
2 <view class="progress_bgs">
3 <view class="progress_bg">
4 <image class="progress_img" src='/images/record.png'></image>
5 </view>
6 </view>
7 </view>
8 <view class='progress_box' bindtap='shutRecording' style="display:{{shutRecordingdis}}">
9 <view class="progress_bgs">
10 <view class="progress_bg">
11 <image class="progress_img" src='/images/stop.png'></image>
12 </view>
13 </view>
14 </view>
15 <view bindtap='recordingAndPlaying' data-soundid="{{soundUrl}}">
16 <image class="progress_img" src='/images/play.png'></image>
17 </view>
里面的图片换成自己的,仅实现功能,没有调播放按钮的位置。
四、WXSS的实现
1 .topicRecording {
2 float: left;
3 width: 40%;
4 height: 100%;
5 position: relative;
6 }
7
8
9 .progress_box {
10 width: 130rpx;
11 height: 130rpx;
12 margin-left: -65rpx;
13 position: absolute;
14 bottom: 0;
15 left: 50%;
16 display: flex;
17 align-items: center;
18 justify-content: center;
19 background: #ccc;
20 border-radius: 50%;
21 }
22
23 .progress_bgs {
24 width: 114rpx;
25 height: 114rpx;
26 background: #fff;
27 border-radius: 50%;
28 margin: 9rpx;
29 }
30
31 .progress_bg {
32 width: 106rpx;
33 height: 106rpx;
34 margin: 5rpx;
35 position: absolute;
36 background: #444;
37 border-radius: 50%;
38 }
39
40 .progress_img {
41 width: 82rpx;
42 height: 82rpx;
43 border-radius: 50%;
44 margin: 12rpx;
45 }
样式借鉴下就好了。