Don't Talk, code is here: 重點是startRecord 方法 <template> <div> <el-tooltip class="item" effect="dark" content="再次點擊 【開始錄音】 即為重新錄製,之前錄製的將被作廢" placement=" ...
Don't Talk, code is here:
重點是startRecord
方法
<template>
<div>
<el-tooltip class="item" effect="dark" content="再次點擊 【開始錄音】 即為重新錄製,之前錄製的將被作廢" placement="top">
<el-button :disabled="isPlay" :icon="isRecording?'el-icon-turn-off-microphone el-icon--right' : 'el-icon-microphone el-icon--right'" plain :type="isRecording ? 'danger' : 'primary'" size="mini" @click="togleAudioRecord">{{ isRecording ? '停止錄音' : '開始錄音' }}</el-button>
</el-tooltip>
<el-button plain :disabled="isRecording" type="info" size="mini" @click="toglePlayRecord">
<svg-icon :icon-class="isPlay ? 'stop-white' :'play-fill-white' " />{{ isPlay ? '停止播放' : '試聽錄音' }}
</el-button>
<el-button icon="el-icon-upload el-icon--right" plain type="success" size="mini" @click="uploadRecord">上傳</el-button>
<span :class="{ 'time-black': isPlay, 'time-red': isRecording && recordingSecond %2 === 0, 'time-pink': isRecording && recordingSecond %2 === 1 }" class="font-bold margin-horizon-10">{{ formatTimeFormSec(recordingSecond) }}</span>
<audio ref="audio" :volume="0.85" @ended="audioPlayEnd" />
</div>
</template>
<script>
export default {
name: 'AudioRecorder',
data() {
return {
isRecording: false,
recordingSecond: 0,
intervalSeed: null,
isPlay: false,
audioStream: null, // 用戶存儲媒體流
audioRecorder: null, // 錄音對象
audioBlob: null, // 錄音文件
audioUrl: null // 錄音文件試聽url
}
},
beforeDestroy() { // 組件銷毀時,停止當前正在執行的操作,釋放資源,防止記憶體泄漏
// 如果正在錄製,則結束錄製
this.isRecording && this.stopRecord()
// 如果正在播放,則停止播放
this.isPlay && this.stop()
},
methods: {
togleAudioRecord() {
this.isRecording = !this.isRecording
if (this.isRecording) { // 需要開始錄音
this.startRecord()
this.startInterval() // 錄音時長計時器
} else { // 需要結束錄音
this.stopRecord()
this.stopInterval()
}
},
toglePlayRecord() {
if (this.audioUrl == null) {
this.$message.error('請先錄製音頻')
return
}
this.isPlay = !this.isPlay
if (this.isPlay) { // 需要播放
this.play()
this.startInterval() // 錄音時長計時器
} else { // 停止播放
this.stop()
this.stopInterval()
}
},
uploadRecord() { // TODO 上傳錄音
},
audioPlayEnd() { // 音頻播放結束將被調用
this.isPlay = false
this.stopInterval()
},
startRecord() { // 開始錄音
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then(stream => {
this.audioStream = stream
this.audioRecorder = new MediaRecorder(stream)
this.audioRecorder.start()
this.audioRecorder.ondataavailable = e => {
this.audioBlob = new Blob([e.data], { type: 'audio/wav' })
this.audioUrl = URL.createObjectURL(this.audioBlob)
this.$refs.audio.src = this.audioUrl
}
})
.catch(err => {
console.log(err)
})
},
stopRecord() { // 結束錄音
this.audioRecorder.stop()
this.audioStream.getTracks().forEach(track => track.stop())
this.audioRecorder = null
this.audioStream = null
this.audioBlob = null
this.audioUrl = null
},
play() { // 開始播放
this.$refs.audio.play()
},
stop() { // 停止播放
this.$refs.audio.currentTime = 0
this.$refs.audio.pause()
},
formatTimeFormSec(sec) { // 將錄製的秒數轉換為 00:01:01 格式的字元串
const h = Math.floor(sec / 3600)
const m = Math.floor(sec % 3600 / 60)
const s = Math.floor(sec % 60)
return (h > 9 ? h : '0' + h) + ':' + (m > 9 ? m : '0' + m) + ':' + (s > 9 ? s : '0' + s)
},
startInterval() { // 開始計時秒數
this.recordingSecond = 0
this.intervalSeed = setInterval(() => {
this.recordingSecond++
}, 1000)
},
stopInterval() { // 停止計時秒數
clearInterval(this.intervalSeed)
} }
}
</script>
<style lang="scss" scoped>
.time-black{
color: #303133;
}
.time-red{
color: #ff0000;
}
.time-pink{
color: #ff6767;
}
.font-bold{
font-weight: bolder;
}
.margin-horizon-10{
margin: 0 10px;
}
</style>
環境
- Vue 2.?
- Element-ui
- Ruoyi-vue
備註
代碼是完整的組件,放在
<el-form-item label="錄音">
<AudioRecorder />
</el-form-item>
顯示起來剛剛好。