- A+
所属分类:Web前端
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>
显示起来刚刚好。