uniapp使用音频录音功能
录音功能
主要根据uniapp官网提供的uni.getRecorderManager() API来实现路由功能,官网地址:https://uniapp.dcloud.net.cn/api/media/record-manager.html
注意:uniapp提供的uni.getRecorderManager()在h5上面不支持,如果h5想实现录音功能使用navigator.mediaDevices.getUserMedia({ audio: true })API来实现
使用全局管理状态管理录音功能
uniapp就支持全局状态管理功能只要文件下创建store文件
index.js
import { createStore } from 'vuex'import audio from './modules/audio'
import user from './modules/user'const store = createStore({modules: {audio,user}
})export default store
audio.js文件
export default {state: {// 存放全局事件events: [],// 录音管理器RECORD: null,RecordTime: 0,RECORDTIMER: null,sendVoice: null},mutations: {initRECORD(state) {state.RECORD = uni.getRecorderManager()// 监听录音开始state.RECORD.onStart(() => {state.RecordTime = 0state.RECORDTIMER = setInterval(() => {state.RecordTime++}, 1000)})// 监听录音结束state.RECORD.onStop(e => {if(state.RECORDTIMER) {clearInterval(state.RECORDTIMER)state.RECORDTIMER = null}// 执行发送if(typeof state.sendVoice === 'function') {state.sendVoice(e.tempFilePath)}})},// 注册发送音频事件regSendVoiceEvent(state, event) {state.sendVoice = event},// 注册全局事件regEvent(state, event) {state.events.push(event)},// 执行全局事件doEvent(state, params) {state.events.forEach(e => {e(params)})},// 注销事件removeEvent(state, event) {let index = state.events.findIndex(item => {return item === event})if(index !== -1) {state.events.splice(index, 1)}}},actions: {// 分发注册全局时间$onAudio({ commit }, event) {commit('regEvent', event)},// 分发执行全局事件$emitAduio({commit}, params) {commit('doEvent', params)},// 分发注销全局事件$offAudio({commit}, event) {commit('removeEvent', event)}}
}
App.vue文件初始化录音功能initRECORD方法
import store from './store';
export default {onLaunch() {// 初始化录音管理器store.commit('initRECORD')}
}
点击录音按钮进行录音
- 页面按钮
<view v-if="mode === 'audio'" class="rounded flex align-center justify-center" :class="isRecording ? 'bg-hover-light':'bg-white'"style="height: 80rpx;" @touchstart="voiceTouchStart" @touchend="voiceTouchEnd"@touchcancel="voiceTouchCancel"@touchmove="voiceTouchMove"
><text class="font">{{ isRecording ? '松开 结束' : '按住 说话' }}</text>
</view>
- 逻辑
import { mapState, mapMutations } from 'vuex'
export default {data() {return {// 音频录制状态isRecording: false,// 取消录音unRecord: false,}},computed: {...mapState({RECORD: state => state.audio.RECORD})},methods: {// 录音相关voiceTouchStart(e) {this.isRecording = truethis.recordingStartY = e.changedTouches[0].clientYthis.unRecord = false// 开始录音this.RECORD.start({format: 'mp3'})},// 录音结束voiceTouchEnd() {this.isRecording = false// 停止录音this.RECORD.stop()},// 录音被打断voiceTouchCancel() {this.isRecording = falsethis.unRecord = true// 停止录音this.RECORD.stop()},voiceTouchMove(e) {let Y = Math.abs(e.changedTouches[0].clientY - this.recordingStartY)this.unRecord = (Y >= 50)},}
}
播放音频功能
<view v-else-if="item.type === 'audio'" class="flex align-center" @click="openAudio"><image v-if="isself" :src="!audioPlaying ? '/static/audio/audio3.png':'/static/audio/play.gif'" style="width: 50rpx;height: 50rpx;" class="mx-1"></image><text class="font">{{item.options.time}}</text><image v-if="!isself" :src="!audioPlaying ? '/static/audio/audio3.png':'/static/audio/play.gif'" style="width: 50rpx;height: 50rpx;"class="mx-1"></image></view>
import { mapState, mapActions } from 'vuex'
export default {data() {return {innerAudioContext: null,}},mounted() {// 注册全局事件if(this.item.type === 'audio') {this.$onAudio(this.onPlayAudio)}},methods: {...mapActions(['$onAudio', '$emitAduio', '$offAudio']),// 播放音频openAudio() {// 通知其他音频this.$emitAduio(this.index)if(!this.innerAudioContext) {this.innerAudioContext = uni.createInnerAudioContext()this.innerAudioContext.src = this.item.datathis.innerAudioContext.play()// 监听播放this.innerAudioContext.onPlay(() => {this.audioPlaying = true})// 监听暂停this.innerAudioContext.onPause(() => {this.audioPlaying = false})// 监听停止this.innerAudioContext.onStop(() => {this.audioPlaying = false})// 监听错误this.innerAudioContext.onError(() => {this.audioPlaying = false})} else {this.innerAudioContext.stop()this.innerAudioContext.play()}},// 监听音频全局事件onPlayAudio(index) {if(this.innerAudioContext) {if(this.index !== index) {this.innerAudioContext.pause()}}},// 关闭音频closeAudio() {if(this.item.type === 'audio') {this.$offAudio(this.onPlayAudio)}// 销毁音频if(this.innerAudioContext) {this.innerAudioContext.destroy()this.innerAudioContext = null}},}
}
H5录音功能
// H5 录音示例
let mediaRecorder;
let audioChunks = [];// 开始录音
export const startRecord = () => {navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {mediaRecorder = new MediaRecorder(stream);audioChunks = [];mediaRecorder.addEventListener("dataavailable", event => {audioChunks.push(event.data);});mediaRecorder.start();}).catch(error => {console.error("无法访问麦克风:", error);});
}// 停止录音
export const stopRecord = () => {return new Promise(resolve => {mediaRecorder.stop();mediaRecorder.addEventListener("stop", () => {const audioBlob = new Blob(audioChunks, { type: "audio/wav" });const audioUrl = URL.createObjectURL(audioBlob);resolve(audioUrl); // 返回录音的临时 URL});});
}