
录音功能
主要根据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
javascript
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文件
javascript
export default {
state: {
// 存放全局事件
events: [],
// 录音管理器
RECORD: null,
RecordTime: 0,
RECORDTIMER: null,
sendVoice: null
},
mutations: {
initRECORD(state) {
state.RECORD = uni.getRecorderManager()
// 监听录音开始
state.RECORD.onStart(() => {
state.RecordTime = 0
state.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方法
javascript
import store from './store';
export default {
onLaunch() {
// 初始化录音管理器
store.commit('initRECORD')
}
}
点击录音按钮进行录音
- 页面按钮
javascript
<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>
- 逻辑
javascript
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 = true
this.recordingStartY = e.changedTouches[0].clientY
this.unRecord = false
// 开始录音
this.RECORD.start({
format: 'mp3'
})
},
// 录音结束
voiceTouchEnd() {
this.isRecording = false
// 停止录音
this.RECORD.stop()
},
// 录音被打断
voiceTouchCancel() {
this.isRecording = false
this.unRecord = true
// 停止录音
this.RECORD.stop()
},
voiceTouchMove(e) {
let Y = Math.abs(e.changedTouches[0].clientY - this.recordingStartY)
this.unRecord = (Y >= 50)
},
}
}
播放音频功能
javascript
<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>
javascript
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.data
this.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录音功能
javascript
// 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
});
});
}