前言
微信小程序中可以實現錄音的主要有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 }
樣式借鑒下就好了。