在Vue中使用音频可视化插件wavesurfer.js__Vue.js
发布于 4 年前 作者 banyungong 4488 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

链接自取

一、基本用法

1.下载wavesurfer.js

$ npm install wavesurfer.js --save
# or 
$ yarn add wavesurfer.js

2.导入

在模块中导入

<script>
  import WaveSurfer from 'wavesurfer.js'
  import Timeline from 'wavesurfer.js/dist/plugin/wavesurfer.timeline'//Timeline插件
  import Region from 'wavesurfer.js/dist/plugin/wavesurfer.regions'//regions插件
  ...
  export default {}
</script>

3.创建一个容器

<template>
  <div>
  	<!-- 时间线容器 -->
   	<div id="timeline" ref="timeline" />
   	<!-- 音频容器 -->
    <div id="waveform" ref="waveform" />
  </div>
</template>

4.创建一个实例

data(){
	return{
     	wavesurfer: '',
     	speed: 1	
    }
},
methods:{
...
this.wavesurfer = WaveSurfer.create({
	container: this.$refs.waveform,//绑定容器,第一种方法
    // container: document.querySelector('#waveform'),//第二种方法
	// container: '#waveform',//第三种方法
	audioRate: this.speed,//控制播放速度
	forceDecode: true,   
	waveColor: '#A8DBA8',
	progressColor: '#3B8686',
	backend: 'MediaElement'
})
this.wavesurfer.load('https://mindflowai-open.oss-cn-hangzhou.aliyuncs.com/505/6mariyokwzjuqjql.wav')//加载音频
...
}


二、Timeline插件

1.导入插件

...
import Timeline from 'wavesurfer.js/dist/plugin/wavesurfer.timeline'
...

2.简单时间线实例

...
this.wavesurfer = WaveSurfer.create({
	container: this.$refs.waveform,
	...
	plugins: [
		Timeline.create({
        	container: '#timeline',//绑定容器
            labelPadding: 2
          })
     ]
})
...

更多参数

3. 自定义复杂时间线

...
Timeline.create({
	container: '#timeline',
	secondaryColor: '#FF0000',//次要时间标签颜色,红色
	secondaryFontColor: '#FF0000',
	secondaryLabelInterval: this._secondaryLabelInterval,
	primaryColor: '#3498DB',//主要时间标签颜色,蓝色
	primaryFontColor: '#D3498DB',
	primaryLabelInterval: this._primaryLabelInterval,
	formatTimeCallback: this._formatTimeCallback,
	timeInterval: this._timeInterval,
	labelPadding: 2
})
...

4.重写formatTimeCallback方法

重写时间线的时间格式:

_formatTimeCallback(seconds, pxPerSec) {
	seconds = Number(seconds)
	var minutes = Math.floor(seconds / 60)
	seconds = seconds % 60
	var secondsStr = Math.round(seconds).toString()
	if (pxPerSec >= 25 * 10) {
        secondsStr = seconds.toFixed(2)
    } else if (pxPerSec >= 25 * 1) {
        secondsStr = seconds.toFixed(1)
    }
    if (minutes > 0) {
    	if (seconds < 10) {
          	secondsStr = '0' + secondsStr
        }
     	return `${minutes}:${secondsStr}`
   	}
    return secondsStr
}

5.重写timeInterval方法

重写时间间隔数,以分钟为单位的持续时间:

/**
* @param pxPerSec
* @return 以分钟为单位的值
*/
_timeInterval(pxPerSec) {
      var retval = 1
      if (pxPerSec >= 100) { // 0.5,1,1.5,2,...,9.5,10
        retval = 0.5
      } else if (pxPerSec >= 80) { // 1,2,...,9,10
        retval = 1
      } else if (pxPerSec >= 60) { // 2,4,6,8,10
        retval = 2
      } else if (pxPerSec >= 40) { // 5,10
        retval = 1
      } else if (pxPerSec >= 20) {
        retval = 5
      } else {
        retval = Math.ceil(0.5 / pxPerSec) * 60
      }
      return retval
},

6.重写primaryLabelInterval方法

重写主要时间标签的数量:

_primaryLabelInterval(pxPerSec) {
      var retval = 1
      if (pxPerSec >= 100) {
        retval = 2
      } else if (pxPerSec >= 80) {
        retval = 1
      } else if (pxPerSec >= 60) {
        retval = 1
      } else if (pxPerSec >= 40) {
        retval = 5
      } else if (pxPerSec >= 20) {
        retval = 2
      } else {
        retval = 1
      }
      return retval
},

7.重写secondaryLabelInterval方法

重写次要时间标签的数量:

_secondaryLabelInterval(pxPerSec) {
      if (pxPerSec >= 20 && pxPerSec < 40) {
        return 12
      } else if (pxPerSec >= 0 && pxPerSec < 20) {
        return 10
      } else {
        return Math.floor(10 / this._timeInterval(pxPerSec))
      }
},

8. timeIntervalprimaryLabelIntervalsecondaryLabelInterval关系

以传入的pxPerSec大于等于100为例,_timeInterval(100)返回0.5,_primaryLabelInterval(100)返回2。此时,主要标签的时间间隔是1秒(0.5*2),由2个0.5组成。_secondaryLabelInterval(100)返回10个1秒


三、方法

1.播放

//play()
this.wavesurfer.play()

2.暂停

//pause()
this.wavesurfer.pause()

3.回到开始并停止

 //stop()
 this.wavesurfer.stop()

4.重播

 //play([start[,end]]),可选参数
this.wavesurfer.play(0)

5.缩放

//zoom(pxPerSec)
this.wavesurfer.zoom(Number(this.valueZoom))

6.播放速度

//setPlaybackRate(rate)
this.wavesurfer.setPlaybackRate(this.speed)

7.调节声音

//setVolume(newVolume)-将播放音量设置为新值[0..1](0 =静音,1 =最大)
this.wavesurfer.setVolume(Number(this.valueRound * 0.01))

8.格式化时间

changeTime(seconds) {
	seconds = Number(seconds)
    var minutes = Math.floor(seconds / 60)
    seconds = seconds % 60
	var secondsStr = Math.round(seconds).toString()
    secondsStr = seconds.toFixed(2)
	if (minutes > 0) {
		return `${minutes < 10 ? '0' + minutes : minutes}:${seconds < 10 ? '0' + secondsStr : secondsStr}`
	}
	return `00:${seconds < 10 ? '0' + secondsStr : secondsStr}`
},

更多方法


四、事件

1.区域插件的region-click事件

点击区域,打印该区域开始和结束的时间:

this.wavesurfer.on('region-click', (e)=> {
	const { start, end } = e
	console.log(this.changeTime(start), this.changeTime(end))
})

2.获取当前播放时间

监听audioprocess事件,返回当前时间:

this.wavesurfer.on('audioprocess', function(e) {
	this.currentTime =this.changeTime(this.wavesurfer.getCurrentTime())
})

五、Regions插件

1.导入

import Region from 'wavesurfer.js/dist/plugin/wavesurfer.regions'

2.初始化

...
this.wavesurfer = WaveSurfer.create({
    container: this.$refs.waveform,
    ...
    plugins: [
        Timeline.create({...}),
        Region.create({
              regions: [
                {
                  start: 1,		//开始时间
                  end: 3,		//结束时间
                  loop: false,	//是否循环播放
                  color: 'hsla(400, 100%, 30%, 0.5)'//区域颜色
                }, {
                  start: 5,
                  end: 7,
                  loop: false,
                  color: 'hsla(200, 50%, 70%, 0.4)'
                }
              ],
              dragSelection: {
                slop: 5
              }
        }),
    ]
})
...

3.需求

  • 新增区域后播放自动播放当前区域音频,并同时新增一条表格信息(包含开始时间、结束时间等);
  • 点击区域自动播放当前区域音频,并高亮对应的表格信息;
  • 删除表格信息的同时,删除在音频中对应的区域;

4.运用

1.获取区域列表

getRegionList(listArr) {
	const _this = this
	_this.tableData = []// 清除
	if (listArr.length !== 0) {
		for (let i = listArr.length - 1; i >= 0; i--) { // 最新的在最前面
			_this.tableData.push({ id: listArr[i].id, startTime: _this.changeTime(listArr[i].start), endTime: _this.changeTime(listArr[i].end) })
		}
		_this.total = listArr.length
	}
}

2.点击区域,播放当前音频

this.wavesurfer.on('region-click', (region, mouseEvent)=> {
	this.currentRegion = region
	region.play() // 播放当前区域,另一种播放方式: this.wavesurfer.play(start, end)
})

3.点击区域,对应的列表项高亮

el-table标签添加row-class-name属性:

<el-table 
	:data="tableData" 
    :row-class-name="tableRowClassName"
>
...
            

tableRowClassName方法如下:

tableRowClassName({ row, rowIndex }) {
	if (this.currentRegion.id === row.id) {//通过区域id来判断
		return 'success-row'
	}
	return ''
}

给表格添加样式:

.el-table .success-row {
  background: #d9e2f8;
}

4.初次获取区域列表,并生成对应的表格

//wavesurfer.regions.list:获取音频中的区域列表
this.regionList = Object.values(this.wavesurfer.regions.list)
//将处理后的数据传入表格
this.getRegionList(this.regionList)

5.新增区域,播放当前音频,新增表格项

this.wavesurfer.on('region-update-end', (region) => {
	/** 播放区域的两种方式 */
	// this.wavesurfer.play(this.currentRegion.start, this.currentRegion.end)//①
	region.play()// ②
    
	/** 新增区域列表 */
	this.regionList = Object.values(this.wavesurfer.regions.list)
	this.getRegionList(this.regionList)
})

6.删除表格项,删除区域

deleteRegion(row) {
	const arr = this.regionList
	if (arr) {
		arr.forEach((region, index) => {
			if (row.id === region.id) {
            	region.remove()
            	arr.splice(index, 1)
            	this.getRegionList(arr)
          	}
        })
    } 
},

六、Cursor插件

1.导入

import Cursor from 'wavesurfer.js/dist/plugin/wavesurfer.cursor'

2.初始化

...
this.wavesurfer = WaveSurfer.create({
    container: this.$refs.waveform,
    ...
    plugins: [
        Timeline.create({...}),
        Region.create({...}),
        Cursor.create({
			showTime: true,
			opacity: 1,
			customShowTimeStyle: {
				'background-color': '#000',
				color: '#fff',
				padding: '2px',
				'font-size': '10px'
			}
		})
    ]
})
...

3.完善样式

到目前为止的光标是全屏显示的,理想的样子是光标只在音频区域显示,需要添加样式如下:

#waveform{
  position: relative;
}

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: Zz燕 原文链接:https://juejin.im/post/6862201364308492302

回到顶部