能力依賴
RecorderManager 全局唯一的錄音管理器
錄音功能的要求與限制
與當前頁面其他音頻播放/錄音功能互斥
是否在錄音中狀態顯示
結束/不需要錄音時,回收RecorderManager對象
材料
可以/結束 錄音 錄音中
Codeing(結果代碼直接看最后)
構造一個簡單的DOM結構
<image @click="recordAction" :src="recordImg" class="record"/>
先實現小程序的錄音功能
import iconRecord from '../../static/images/icon_record.png' import iconRecording from '../../static/images/icon_recording.png' // ... data() { recordImg: iconRecord, // 錄音按鈕的圖標 rm: null, // 錄音管理器 }, // ... mounted() { if (this.rm === null) { // 錄音管理器如果沒有初始化就先初始化 this.rm = uni.getRecorderManager() } // 綁定回調方法 this.rm.onStart((e) => this.onStart(e)) this.rm.onPause((e) => this.onPause(e)) this.rm.onResume((e) => this.onResume(e)) this.rm.onInterruptionBegin((e) => this.onInterruptionBegin(e)) this.rm.onInterruptionEnd((e) => this.onInterruptionEnd(e)) this.rm.onError((e) => this.onError(e)) }, // ... methods: { // ... recordAction() { if (this.recordImg === iconRecord) { // 設置格式為MP3,最長60S,采樣率22050 this.rm.start({ duration: 600000, format: 'mp3', sampleRate: 22050, }) // 開始錄音后綁定停止錄音的回調方法 this.rm.onStop((e) => this.onStop(e)) } else if (this.recordImg === iconRecording) { this.rm.stop() }, }, onStart(e) { console.log('開始錄音', this.question, this.subQuesIndex) this.recordImg = iconRecording console.log(e) }, onPause(e) { console.log(e) afterAudioRecord() }, onResume(e) { console.log(e) }, onStop(e) { console.log(e) this.recordImg = iconRecord // 結束錄音之后上傳錄音 this.uploadMp3Action(e) }, onInterruptionBegin(e) { console.log(e) }, onInterruptionEnd(e) { console.log(e) }, onError(e) { console.log(e) }, uploadMp3Action(e) { // TODO uploadMp3 }, },
只能同時有一個錄音,與音頻播放互斥
globalData中增加兩個屬性audioPlaying,audioRecording
// src/App.vue export default { globalData: { // 保證全局只有一個音頻處于播放狀態且錄音與播放操作互斥 audioPlaying: false, audioRecording: false, }, // ... },
Util中增加判斷方法
// src/lib/Util.js // 結束錄音之后釋放錄音能力 export function afterAudioRecord() { getApp().globalData.audioRecording = false } // 結束音頻播放之后釋放音頻播放能力 export function afterAudioPlay() { getApp().globalData.audioPlaying = false } /** * 判斷是否可以錄音或者播放 * @param {string} type play | record */ export function beforeAudioRecordOrPlay(type) { const audioPlaying = getApp().globalData.audioPlaying const audioRecording = getApp().globalData.audioRecording if (audioPlaying ||audioRecording) { uni.showToast({ title: audioPlaying ? '請先暫停其他音頻播放' : '請先結束其他錄音', icon: 'none' }) return false } else { if (type === 'play') { getApp().globalData.audioPlaying = true } else if (type === 'record') { getApp().globalData.audioRecording = true } else { throw new Error('type Error', type) } return true } }
改造原有recordAction方法
import { beforeAudioRecordOrPlay, afterAudioRecord} from '../../lib/Utils'; // ... recordAction() { - if (this.recordImg === iconRecord) { + if (this.recordImg === iconRecord && beforeAudioRecordOrPlay('record')) { // 設置格式為MP3,最長60S,采樣率22050 this.rm.start({ duration: 600000, format: 'mp3', sampleRate: 22050, }) // 開始錄音后綁定停止錄音的回調方法 this.rm.onStop((e) => this.onStop(e)) } else if (this.recordImg === iconRecording) { this.rm.stop() + afterAudioRecord() }, },
這樣就避免了多次錄音
小程序錄音上傳
補全我們的uploadMp3Action方法,我們使用uni-app的uni.uploadFile()方法來上傳錄音文件
uploadMp3Action(e) { const filePath = e.tempFilePath const option = { url: 'xxx', filePath, header, formData: { filePath }, name: 'audio', } uni.showLoading({ title: '錄音上傳中...' }) return await uni.uploadFile(option) uni.hideloading() }
最后在頁面卸載的時候回收RecorderManager對象
beforeDestroy() { this.rm = null }
打完收工~