WaveSurfer.js是一个开源的音频可视化库,用于创建交互式、可定制的波形。文章详细介绍了配置选项,包括播放速度、音频渲染、波形样式、交互性等,并提供了事件处理方法如播放、暂停、音量控制等。本文要实现的效果图如下:
安装
按照官方文档步骤
1.安装
npm install --save wavesurfer.js
2.引入
import WaveSurfer from 'wavesurfer.js' //需要时间轴的话需要引入 import Timeline from 'wavesurfer.js/dist/plugins/timeline.esm.js'
封装Vue 组件
接下来,我们将 WaveSurfer.js 封装成一个 Vue 组件,方便在项目中复用。以下是完整的组件代码
<template> <div id="aiccAudio"> <el-card> <div id="wavefrom" ref="wavefrom" @click="getTime"> </div> </el-card> <div class="audio-controlBar"> <!-- 播放/暂停按钮 --> <button @click="playMusic"> <i v-if="videoPlay" class="el-icon-video-play"></i> <i v-else class="el-icon-video-pause"></i> </button> <!-- 时间 --> <div class="audio-time"> <div class="audio-current-time" aria-label="time">{{ currentTime }}</div> <span class="audio-fen-line">|</span> <div class="audio-duration" aria-label="duration">{{ duration }}</div> </div> <!-- 倍速 --> <span style="margin-left: 80px;margin-right: 10px;">倍速</span> <el-select class="audio-speed" v-model="speedValue" @change="speedChange"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> <!-- <span class="audio-line">|</span> --> <!-- 音量 --> <div class="audio-volume"> <img v-if="audioVolumeStatus == true" @click="volumeStatusChange('open')" class="audio-volume-img" src="../../../../public/images/voice_open.png"> <img v-else class="audio-volume-img" @click="volumeStatusChange('close')" src="../../../../public/images/voice_close.png"> <el-slider class="audio-volume-slider" v-model="volume" @input="volumeChange"></el-slider> </div> </div> </div> </template> <script> import WaveSurfer from 'wavesurfer.js' //导入wavesurfer.js import Timeline from 'wavesurfer.js/dist/plugins/timeline.esm.js' //导入时间轴插件 export default { name: 'AiccAudio', props: { src: { type: String }, recordPath: { type: String } }, data() { return { wavesurfer: null, timer: null, options: [ { value: '0.5', label: '0.5', }, { value: '1.0', label: '1.0', }, { value: '1.5', label: '1.5', }, { value: '2.0', label: '2.0', } ], speedValue: '1.0', currentTime: '00:00:00', //当前播放 duration: '00:00:00', //总时长 volume: 30,//音量, audioVolumeStatus: false, //是否静音 videoPlay: true, } }, created() { this.keyDown(); }, mounted() { this.$nextTick(() => { if (this.recordPath != null && this.recordPath != '') { this.wavesurfer = WaveSurfer.create({ container: this.$refs.wavefrom, height: 128, waveColor: 'rgb(200, 0, 200)', progressColor: '#00f2fe', cursorColor: '#00f2fe', //指示播放头位置的光标填充颜色 cursorWidth: 2, // backend: 'MediaElement', mediaControls: false, audioRate: this.speedValue, hideScrollbar: true, setPlaybackRate: [0.5, 1.0, 1.5, 2.0], //使用时间轴插件 plugins: [Timeline.create()], }) this.wavesurfer.load('http://localhost:9527/89A3099B9253566.mp3') console.log(this.wavesurfer) //音频加载完成触发 this.wavesurfer.on("ready", () => { this.wavesurfer.setVolume(this.volume / 100); this.duration = this.formatSecond(this.wavesurfer.getDuration()) }); this.wavesurfer.on('click', () => { this.wavesurfer.play() this.videoPlay = false }) } }) }, methods: { getSoundUrl(options) { // 具体请求怎么写就看每个人的项目用的是什么了 return axios.get(url, { responseType: 'blob' }) .then(res => { if (!res.headers['content-disposition']) { return console.error('文件名称不存在'); } // 获取到的blob类型文件地址 return URL.createObjectURL(res.data); }) .catch(err => { console.error('文件获取失败'); }) }, playMusic() { if (this.recordPath != null && this.recordPath != '') { //"播放/暂停"按钮的单击触发事件,暂停的话单击则播放,正在播放的话单击则暂停播放 this.wavesurfer.playPause.bind(this.wavesurfer)(); //每秒获取进度 有时间轴时使用 // this.getProcess(); //判断是否播放 this.videoPlay = this.wavesurfer.isPlaying() == true ? false : true; //音频播放时触发 this.wavesurfer.on("audioprocess", () => { this.currentTime = this.formatSecond(this.wavesurfer.getCurrentTime()) }) //结束播放 this.wavesurfer.on("finish", () => { this.wavesurfer.stop(); this.videoPlay = true; this.currentTime = '00:00:00' }); } }, formatSecond(seconds) { // console.log(seconds) // 确保输入是数字类型 if (typeof seconds !== 'number' || isNaN(seconds)) { this.$message.error('error') } // 将秒数拆分为小时、分钟和秒 const totalSeconds = Math.floor(seconds); // 只保留整数部分 const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0'); // 计算小时并补零 const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(2, '0'); // 计算分钟并补零 const secs = String(totalSeconds % 60).padStart(2, '0'); // 计算秒并补零 return `${hours}:${minutes}:${secs}`; }, //有时间轴时使用 // getProcess(){ // if(this.wavesurfer.isPlaying()){ // this.timer=setInterval(()=>{ // this.percent=(this.wavesurfer.getCurrentTime().toFixed(0)/this.wavesurfer.getDuration()*100).toFixed(0) // this.config={ // value:this.percent // } // },1000) // }else{ // clearInterval(this.timer) // } // }, //点击获取点击进度 getTime() { if (this.recordPath != null && this.recordPath != '') { //加定时器,不然获取的是点击前的播放时间 setTimeout(() => { this.currentTime = this.formatSecond(this.wavesurfer.getCurrentTime()) ///有时间轴时使用 // this.percent=(this.wavesurfer.getCurrentTime()/this.wavesurfer.getDuration()*100).toFixed(0) // this.config={ // value:this.percent // } }, 100) } }, //按键跳转进度 // jump(e){ // this.wavesurfer.play([e.target.innerHTML-0]) // this.percent=(this.wavesurfer.getCurrentTime().toFixed(0)/this.wavesurfer.getDuration()*100).toFixed(0) // this.config={ // value:this.percent // } // this.getProcess() // }, // 监听键盘 keyDown() { if (this.recordPath != null && this.recordPath != '') { document.onkeydown = (e) => { //事件对象兼容 var eCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode; //键盘按键判断:左箭头-37;上箭头-38;右箭头-39;下箭头-40 //左 if (eCode == 37) { // 按下左箭头 this.wavesurfer.skip(-6) this.getTime() } else if (eCode == 39) { // 按下右箭头 this.wavesurfer.skip(6) this.getTime() } } } }, //倍速 speedChange(val) { if (this.recordPath != null && this.recordPath != '') { this.speedValue = val; this.wavesurfer.setPlaybackRate(this.speedValue) } }, //音量大小改变 volumeChange(val) { if (this.recordPath != null && this.recordPath != '') { this.volume = val; if (this.wavesurfer != null) { this.wavesurfer.setVolume(val / 100); } if (val == '0') { this.audioVolumeStatus = false } else { this.audioVolumeStatus = true } } }, //静音开启关闭 volumeStatusChange(status) { if (this.recordPath != null && this.recordPath != '') { if (status == 'open') { this.audioVolumeStatus = false this.volume = 0; this.wavesurfer.setVolume(0); } else { this.audioVolumeStatus = true this.volume = 30; this.wavesurfer.setVolume(30 / 100); } } } } } </script> <style lang="scss" scoped> .audio-controlBar { background-color: #f4f6f9; padding: 0 10px; border-radius: 10px; button { border: none; background-color: #f4f6f9; } i { //color: #95979f; color: #1053ee; } } //时间 .audio-time { display: inline-block; font-size: 12px; color: #95979f; margin: 0 10px; } .audio-current-time { display: inline-block; color: #1053ee; } .audio-fen-line { margin: 0 5px; } .audio-duration { display: inline-block; } //倍速 .audio-speed { width: 68px; // margin-left: 85px; .el-input__inner { background-color: #f4f6f9; } } .audio-line { color: #95979f; margin-right: 5px; } //音量条 .audio-volume { width: 166px; float: right; .audio-volume-slider { width: 110px; float: right; } } .audio-volume-img { width: 18px; margin-top: 12px; } </style>
我为了方便测试,音频路径是写在里面的,有用的同学可以根据项目需求传入组件中,样式功能啥的可以自行调整。
总结
通过 WaveSurfer.js,我们可以轻松实现音频的可视化与播放控制。本文介绍的 Vue 组件封装了常见的音频播放功能,包括播放/暂停、倍速控制、音量调节等,方便在项目中复用。根据项目需求,可以进一步调整样式和功能。
以上就是Vue使用wavesurfer.js实现音频可视化的示例详解的详细内容,更多关于Vue wavesurfer.js音频可视化的资料请关注站长网其它相关文章!