Appearance
音频录制
音频工厂函数封装
- 1、调用音频工厂函数时会自动实例化一个音频实例对象,并且把开始、结束、音频上传等函数,进行二次封装提供给执行者
- 2、在执行开始录音函数时,内部会自动标录音状态,并且开始进行录音,自动监听音频流存储在队列中,同时内部自动开一个一个定时器,用来计算录音的时长
- 3、在执行录音结束函数时,更新录音状态,并且自动的清除定时器
js
import axios from 'axios'
import { Ref, ref } from 'vue'
export interface InstanceRecord {
startRecord: () => void
stopRecord: () => void
uploadAudio: () => void
audioStream: Ref<Blob[]>
playAudioStream: () => void
audioUrl: Ref<string>
checkRecordedAudio: Ref<boolean>
durationStr: Ref<string>
duration: Ref<number>
}
export default async function useRecord(maxDuration = 60): Promise<InstanceRecord> {
const audioStream = ref<Blob[]>([])
const audioUrl = ref<string>('')
const checkRecordedAudio = ref<boolean>(false)
const durationStr = ref<string>('')
const duration = ref<number>(0)
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
const mediaRecorder = new MediaRecorder(stream)
// 开始录制音频
const startRecord = () => {
let timer: any = 0
audioStream.value = []
mediaRecorder.start()
durationStr.value = ''
duration.value = 0
const startTime = new Date().getTime()
checkRecordedAudio.value = true
const secondsToMinutes = (seconds: number) => {
const minutes = Math.floor(seconds / 60)
const remainingSeconds = seconds % 60
return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`
}
const computedDuration = () => {
const endTime = new Date().getTime()
duration.value = (endTime - startTime) / 1000
durationStr.value = secondsToMinutes(parseInt(String(duration.value)))
if (duration.value >= maxDuration) {
mediaRecorder.stop()
}
}
computedDuration()
timer = setInterval(computedDuration, 1000)
mediaRecorder.addEventListener('dataavailable', (event: BlobEvent) => {
audioStream.value.push(event.data)
})
// 音频录制结束
mediaRecorder.addEventListener('stop', () => {
checkRecordedAudio.value = false
clearInterval(timer)
computedDuration()
})
}
const stopRecord = () => {
mediaRecorder.stop()
}
// 音频上传
const uploadAudio = () => {
const blob = new Blob(audioStream.value, { type: 'audio/ogg; codecs=opus' })
const formData = new FormData()
formData.append('file', blob)
axios({
method: 'post',
url: 'http://localhost:3000/upload/record',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
}).then((res) => {
audioUrl.value = res.data.url
})
}
// 播放音频
const playAudioStream = () => {
const blob = new Blob(audioStream.value, { type: 'audio/ogg; codecs=opus' })
const audio = new Audio(URL.createObjectURL(blob))
audio.play()
}
return {
startRecord,
stopRecord,
uploadAudio,
audioStream,
playAudioStream,
audioUrl,
checkRecordedAudio,
durationStr,
duration,
}
}