阅读 1269
上手wavesurfer.js这篇就够了

上手wavesurfer.js这篇就够了

wavesurfer.js是基于Web Audio API 和HTML5 Canvas实现的一个可定制化的音频波形可视化组件,在需要音频波形展示及音频波形交互的场景有广泛的应用。本文经过实践之后,通过官方文档的翻译以及自己的理解做了一个整理工作(接下来还会有具体实践相关的详细文章出来)

1. 使用场景

在某些需要对音频进行波形展示及交互的场景如:

支持音频波形展示

  • 可以对波形进行选择并填写标注信息
  • 随意修改或者拖动选中波形区间
  • 支持打标数据反向渲染波形,并可以修改已打标数据

经过调研之后,发现wavesurfer.js是一款应用十分广泛并且强大、可灵活定制的音频波形可视化组件,可以完全满足我们的音频打标组件需求。

2. wavesurfer.js引入

1. script标签引入:

<script src="https://unpkg.com/wavesurfer.js"></script>

 2. 一般我们推荐npm 安装引入:

npm install wavesurfer.js 
复制代码

 代码import:

import WaveSurfer from 'wavesurfer.js' 
// 创建wavesurfer 实例

var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    scrollParent: true
});
复制代码

3. wavesurfer介绍

通过其官方文档可以发现,wavesurfer 由一些创建实例时的选项(Options)、实例方法(Methods)、监听事件(Events)及一些插件(Plugins)组成。了解了这三点基本上就可以算是完全掌握了wavesurfer,可以来实现音频波形展示及交互的基本需求。

3.1 选项

Options 就是创建wavesurfer 实例时可以传的一些配置参数,通过create创建wavesurfer实例时传入,是对wavesurfer实例的一些基本设置,传入形式如下:

var wavesurfer = WaveSurfer.create({ 
     container: this.$refs.wavesurfer,
     progressColor: '#fff',
     backend: 'MediaElement',
     waveColor: '#666',
     height: 80,
     width: 400,
     normalize: true,
     mediaControls: true,
     preload: true,
     ...

 })
复制代码

 选项参数如下:

optiontypedefaultdescription
audioRatefloat1音频播放速度,数值越小越慢
audioContextobjectnone自己的音频上下文,可以类比于canvas中的context,其中包含一些列
audioScriptProcessorobjectnone使用自己先前初始化的ScriptProcessorNode,就是自定义javaScript生成、处理或者分析音频
autoCenterbooleantrue如果有滚动条,将波形根据进度居中
backendstringWebAudio可选WebAudio, MediaElement or MediaElementWebAudio.
backgroundColorstringnone波形图容器的背景色
barGapnumbernone波形条间距,如未提供将自动计算
barHeightnumber1波形条的高度,大于1的数字将增加波形条的高度
barMinHeightnumbernull绘制波形条的最小高度,默认在静音期间不绘制波形条
barRadiusnumber0波形条的radius
barWidthnumbernone如果指定,波形将如下展示: ▁ ▂ ▇ ▃ ▅ ▂
closeAudioContextbooleanfalse调用destroy方法时,关闭并取消所有音频上下文
containermixednone音频 波形容器的CSS选择器或HTML元素,这是唯一必传的参数
cursorColorstring#333光标的填充颜色,指示播放头的位置
cursorWidthinteger1光标宽度,单位pixels
drawingContextAttributesobject{desynchronized: true}指定canvas 2d 绘图 上下文属性
fillParentbooleantrue是否填充整个容器或仅根据 minPxPerSec进行绘制
forceDecodebooleanfalse缩放以获得更详细的波形时,是否使用web音频强制解码音频
heightinteger128波形的高度,以像素为单位
hideScrollbarbooleanfalse是否隐藏水平滚动条
interactbooleantrue初始化时是否启用鼠标交互。之后可以随时切换该参数
loopSelectionbooleantrue(与区域插件一起使用)启用选定区域的循环
maxCanvasWidthinteger4000单个画布的最大宽度(以像素为单位),不包括小的重叠 (2 * pixelRatio,四舍五入到下一个偶数整数)。如果波形的长度大于此值,则将使用其他画布来渲染该波形,这对于非常大的波形很有用,对于浏览器而言太大的波形可能无法在单个画布上绘制,次参数用于 MultiCanvas 绘制
mediaControlsbooleanfalse(与 MediaElement一起使用) 为true则将启动媒体元素的本机控件
mediaTypestringaudio'audio' 或者 'video'. 与 MediaElement一起使用
minPxPerSecinteger50音频每秒最小像素数
normalizebooleanfalse如果为true,则以最大峰值而非1.0进行归一化
partialRenderbooleanfalse使用PeakCache改善大波形的渲染速度.
pixelRatiointegerwindow.devicePixelRatio可以设置为1以加快渲染速度
pluginsarray[]实例化期间要注册的一组插件定义。除非将 deferInit 属性设置为 true.否则他们将被直接初始化
progressColorstring#555光标后面的波形部分的填充色.当 progressColor 和 waveColor 一样时完全不渲染进度波.
regionsMinLengthnumbernull区域的默认 minLength 以秒为单位.创建区域时,为该区域指定 minLength 将覆盖此参数
removeMediaElementOnDestroybooleantrue为false时当player被销毁时在DOM中保留media 元素.通过loadMediaElement方法重用现有媒体元素时,此功能很有用
rendererObjectMultiCanvas可用于注入自定义渲染器.
responsiveboolean or floatfalse如果为 true ,则在调整窗口大小时,调整波形大小,默认情况下会以每100ms去抖,如果此参数传入的是数字则表示去抖的时间频率
scrollParentbooleanfalse是否以较长的波形滚动容器,否则波形将缩小到容器的宽度 (参考参数 fillParent).
skipLengthfloat2使用 skipForward() 和 skipBackward() 方法跳过的秒数.
splitChannelsbooleanfalse对于不同通道的音频使用分开的波形渲染
splitChannelsOptionsobject{}分离音频通道的选项. 仅在 splitChannels=true时有效.请参阅下面的选项.
splitChannelsOptions.overlaybooleanfalse叠加通道的波形,而不是在单独的行上渲染它们
splitChannelsOptions.relativeNormalizationbooleanfalse归一化可保持通道之间的比例,仅在 normalize=true 时适用
splitChannelsOptions.filterChannelsarray[]从渲染波形中排除的通道号列表. 通道以0开始索引
splitChannelsOptions.channelColorsobject{}覆盖每个通道的颜色,每个key指示一个通道号,而对应的值是一个描述其颜色特征的对象.例如: channelColors={ 0: { progressColor: 'green', waveColor: 'pink' }, 1: { progressColor: 'orange', waveColor: 'purple' } }
waveColorstring#999光标后的波形填充颜色.
xhrObject{}XHR 选项. 例如: let xhr = { cache: 'default', mode: 'cors', method: 'GET', credentials: 'same-origin', redirect: 'follow', referrer: 'client', headers: [ { key: 'Authorization', value: 'my-token' } ]}; (因为音频波形的解析是要发异步请求的,所以可能存在一些网络请求的问题需要设置的,这个选项就可以用到)

3.2 方法

创建完wavesurfer实例之后,就可以通过创建的实例来调用这些方法了。下面梳理了所有方法及其含义和用法。

  • cancelAjax() – 取消音频文件加载过程.
  • destroy() – 移除事件、 元素 以及 断开Web Audio节点的连接.
  • empty() – 清空波形.
  • getActivePlugins() – 返回当前已初始化插件的map.
  • getBackgroundColor() –返回波形容器的背景色.
  • getCurrentTime() – 以秒为单位返回当前进度.
  • getCursorColor() – 返回指示播放头位置的光标填充颜色.
  • getDuration() – 返回音频的时长.
  • getPlaybackRate() – 返回音频片段的播放速度.
  • getProgressColor() – 返回光标后面波形的填充颜色.
  • getVolume() – 返回当前音频段的音量.
  • getMute() – 返回当前的静音状态.
  • getFilters() – 返回当前设置的过滤器数组.
  • getWaveColor() –返回光标后的波形填充颜色.
  • exportPCM(length, accuracy, noWindow, start) –导出 PCM data 为一个json数组. 参数: length [number] - default: 1024, accuracy [number] - default: 10000, noWindow [true|false] - default: false, start [number] - default: 0
  • exportImage(format, quality, type) – 以data URI 或 Blob的方式返回波形图的图片.
  • isPlaying() – 返回当前是否正在播放.
  • load(url, peaks, preload) – 加载音频URL 通过 XHR. 可选的参数:峰值 peaks 数组,preload [none|metadata|auto], 如果使用MediaElement将传给Audio元素.
  • loadBlob(url) –通过 Blob 或 File 对象加载音频.
  • on(eventName, callback) – 事件监听. 参考 WaveSurfer Events 查看所有事件列表.
  • un(eventName, callback) – 取消事件监听.
  • unAll() – 取消所有事件监听.
  • pause() – 暂停.
  • play([start[, end]]) – 从当前位置播放.可选的以秒为单位的开始和结束可用于设置要播放的音频范围.
  • playPause() – 如果处于暂停状态就播放, 如果处于播放状态就暂停.
  • seekAndCenter(progress) – 进度跳转并居中当前进度试图居中(0 = beginning, 1 = end).
  • seekTo(progress) – 进度跳转 (0 = beginning, 1 = end).
  • setBackgroundColor(color) – 设置波形容器的背景色.
  • setCursorColor(color) – 设置播放光标的背景色.
  • setHeight(height) – 设置波形高度.
  • setFilter(filters) - 用于将自己的WebAudio 节点插入图中. 具体见Connecting Filters .
  • setPlaybackRate(rate) – 设置重放速度 (0.5 半速, 1 正常速度, 2 倍速 如此类推).
  • setPlayEnd(position) – 设置以秒为单位的播放暂停点.
  • setVolume(newVolume) – 设置播放音量[0..1] (0 静音, 1 最高音量).
  • setMute(mute) – 将当前声音静音,布尔值true静音,false取消静音.
  • setProgressColor(color) – 设置光标前面波形的填充颜色.
  • setWaveColor(color) – 设置光标后面波形的填充颜色.
  • skip(offset) – 从当前位置跳过几秒钟(使用负值像后移动)
  • skipBackward() - 倒带跳过的 skipLength 的秒数.
  • skipForward() - 向前跳过的 skipLength 的秒数.
  • setSinkId(deviceId) - 设置接收器ID以更改音频输出设备.
  • stop() – 暂停并回到起点.
  • toggleMute() – 切换声音开关.
  • toggleInteraction() – 切换鼠标交互开关.
  • toggleScroll() – 切换 scrollParent.
  • zoom(pxPerSec) – 水平放大或缩小波形,参数是每秒音频的水平像素,设置这个会更改参数minPxPerSec  并启用scrollParent选项

3.3 事件

wavesufer同样提供了很多事件,供我们再不同场景灵活使用。事件的订阅和取消订阅通过on()和un()

wavesurfer.on('pause', function () { wavesurfer.params.container.style.opacity = 0.9; });  

wavesufer所有事件如下:

  • audioprocess – 音频进度监听,在音频播放时持续出发seeking时也会触发.
  • dblclick – 当实例被双击时触发.
  • destroy – 当实例被销毁时触发.
  • error – 错误监听,出现错误时触发. 回调函数会将字符串类型的错误信息带回。.
  • finish – 播放完成时触发.
  • interaction – 与波形交互时触发.
  • loading – 使用fetch、drag或drop的时候会持续触发. 回调函数将接收加载(整数)进度的百分比 [0..100].
  • mute – 静音状态改变时触发. 回调接收新的静音状态.
  • pause – 音频暂停时触发.
  • play – 开始播放时触发.
  • ready – 音频加载后,解码并绘制波形时触发. 在使用MediaElement时在波形绘制前触发, 详情参考waveform-ready.
  • scroll - 当滚筒条移动时触发,回调接收ScrollEvent对象.
  • seek – seeking时触发. 回调接收(浮点) 进度 [0..1].
  • volume – 音量改变时触发. 回调接收 (整数) 新音量值.
  • waveform-ready – 使用MediaElement时绘制波形之后触发; 如果使用的是WebAudio, 可以使用ready 监听.
  • zoom – 波形缩放时触发. 回调函数将接收(整数) minPxPerSec值.

 

3.4 插件

到此其实就已经可以灵活使用wavesurfer来生成音频波形了。为了更好的用户体验wavesurfer还提供了很多插件来满足不同的需求,比如区域选择,时间线等。下面就就介绍一下常用的一些插件: Regions 、TimelineMinimapCursor

如果要使用插件,首先需要引入插件,插件的引入如下

#html全局引入
<script src="https://unpkg.com/wavesurfer.js"></script>
<script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.minimap.min.js"></script>

#js动态引入
import MinimapPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.minimap.min'
import CursorPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.cursor.min'
import RegionsPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.regions.min'
import TimelinePlugin from 'wavesurfer.js/dist/plugin/wavesurfer.timeline.min'
复制代码

 并且在创建WaveSurfer实例的时候,需要引入plugins的配置。各种插件在被引入之后要在plugins参数里配置。如下:

var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    plugins: [
        WaveSurfer.regions.create({})
        // TimelinePlugin.create({})  //按照import引入写法
    ] 
});
复制代码

3.4.1 Regions 插件

Regions插件是通过在波形上叠加一层来标识用于循环播放的片段,可以拖动位置或者调整大小。可以感受一下官方提供的实例

image.png Regions-demo

3.4.1.1 直接添加到WaveSurfer实例上的方法

Regions提供一些直接添到WaveSurfer实例上的方法(也就是可以直接通过wavesurfer实例直接调用的方法):

addRegion(options) – 在波形上创建一个区域并返回一个Region对象.Region对象的属性参考下面的Region的选项, Region 的方法 和 Region的事件。(注意:在音频加载完成之前不能添加区域片段,否则新片段的start和end属性将被设置为0,或者一个意外的值) clearRegions() – 移除所有的region片段. enableDragSelection(options) – 允许在创建region片段的时候通过鼠标选择波形区域. options 参考下面的regions options的配置. 备注:通过 wavesurfer.regions.list可以获取所有的region列表。

如下代码,在创建完包含Regions插件的wavesurfer实例之后,就可以直接基于wavesurfer实例来调用上面的这些方法方法,如下示例:

var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    plugins: [
        WaveSurfer.regions.create({...regionsOptions})
    ]
});
//创建region
const curRegion = wavesurfer.addRegion({
 start: 10,
 end: 20,
 loop: false,
 drag: false,
 resize: false,
 color: 'rgb(217, 184, 241, 0.8)'
 })
复制代码

3.4.1.2 Options选项

Region对象 有如下 options,在创建region实例的时候可以使用这些选项设置:

optiontypedefaultdescription
idstringrandomregion 区域的id
startfloat0region 的开始时间(秒)
endfloat0region 的结束时间(秒)
loopbooleanfalse是否循环播放region.
dragbooleantrue是否允许拖动region.
resizebooleantrue是否允许调整区域大小.
colorstring"rgba(0, 0, 0, 0.1)"区域的色值.
minLengthnumbernull区域的最小长度 (单位秒).
maxLengthnumbernull区域的最大长度(单位秒).

3.4.1.3 Region实例的方法

通过addRegion创建的Region实例的方法。

  • play() - 从头到尾播放region一次.
  • playLoop() - 循环播放 该region.
  • remove() - 移除该region.
  • onDrag(timeInSeconds) -将 timeInSeconds值 做加法加到 start 和 end 参数上.
  • onResize(timeInSeconds, 'start') - 默认将 timeInSeconds 加到 end 参数上. 可选参数'start' 会将  timeInSeconds 加到 start上去.

3.4.1.4 事件

每一个 region 对象 都有如下 事件:

一般事件:

  • in - 当播放进入区域时。
  • out - 当播放离开区域.
  • remove - 区域被移除之前触发.
  • update - 当区域的选项options被更新.
  • update-end - 当dragging 或resizing 完成之后.

鼠标事件:

  • click - 当鼠标点击区域时.回调将接收一个鼠标事件.
  • dblclick - 双击区域时触发. 回调将接收一个鼠标事件.
  • over -鼠标移动过该区域时触发.回调将接收一个鼠标事件.
  • leave - 鼠标离开区域时触发.回调将接收一个鼠标事件.

WaveSurfer事件:

 WaveSurfer 实例还会触发一组匹配事件(传递区域对象):

  • region-created
  • region-updated
  • region-update-end
  • region-removed
  • region-play
  • region-in
  • region-out
  • region-mouseenter
  • region-mouseleave
  • region-click
  • region-dblclick

 

3.4.2 Timeline 插件

Timeline是给wavesurfer添加时间线

如图:

image.png 实例:Timeline-demo

同Regions插件的引入,在创建Wavesurfer实例时需要引入插件,基本用法如下:

var wavesurfer = WaveSurfer.create({
    container: '#waveform',
    plugins: [
        WaveSurfer.timeline.create({
              container: "#wave-timeline"
        })   
    ] 
});
复制代码

timeline的选项:

  • container - 必传- 放置时间轴的元素,或用于查找它的 CSS 选择器
  • height - 时间线的高度(以像素为单位)。默认值为 20.
  • notchPercentHeight - 时间线中次要缺口线的高度(以百分比表示)。默认值为 90。
  • primaryColor - 模十凹口线的颜色(例如 10 秒、20 秒)。默认值为“#000”。
  • secondaryColor - 非模十凹口线的颜色. 默认值为'#c0c0c0'.
  • primaryFontColor - 主要凹口旁边的标签颜色(例如 10 秒、20 秒)。默认值为“#000”。
  • secondaryFontColor - 次要槽口旁边的标签颜色(例如 5 秒、15 秒)。默认值为“#c0c0c0”。
  • timeInterval -number of intervals that records consists of. Usually it is equal to - the duration in minutes. (Integer or function which receives pxPerSec value and reurns value)   (英文更好理解,暂不翻译)
  • primaryLabelInterval - number of primary time labels. (Integer or function which - receives pxPerSec value and reurns value)
  • secondaryLabelInterval - number of secondary time labels (Time labels between primary labels, integer or function which receives pxPerSec value and reurns value).     (英文更好理解,暂不翻译)
  • formatTimeCallback - 自定义时间格式回调。 (接收秒数并返回格式化字符串的函数)
  • offset - 时间轴开始的偏移量(以秒为单位)。该值也可能为负数,默认为 0.

3.4.3 Minimap 插件

如图下图,为整个音频波形增加一个缩略图的展示,可以通过实例Minimap-demo来感受一下。

image.png

引入方式如下:

var wavesurfer = WaveSurfer.create({
    // your options here
    plugins: [
        WaveSurfer.minimap.create({
            container: '#wave-minimap', // 缩略图容器id
            waveColor: '#777',  //缩略图波形颜色
            progressColor: '#222',  //播放过的波形颜色
            height: 50    //缩略图高度
        })
    ]
});

复制代码

3.4.4 Cursor 插件

如图下图,Cursor插件主要用处是为wavesurfer增加鼠标位悬停处时间的展示如图:可以看到鼠标右边有展示当前位置的具体时间精确到毫秒数,也可以通过demo实际感受一下Cursor-demo

image.png

具体用法如下:

let wavesurfer = WaveSurfer.create({
    container: document.querySelector('#waveform'),
    plugins: [
        WaveSurfer.cursor.create({
            showTime: true,  //是否显示时间
            opacity: 1,  //光标及时间整个组件的透明度
            customShowTimeStyle: {  //时间展示的设置
                'background-color': '#000',  //时间展示块的背景色
                color: '#fff',  //时间展示文字的颜色
                padding: '2px',  //时间展示块的padding
                'font-size': '10px'  //时间展示文字的font-size
            }
        })
    ]
});
复制代码

除了以上一些常用的插件,wavesurfer还有其它一些插件,如果有需要可以参考wavesurfer-js.org/plugins/

文章参考:wavesurfer-js.org/

文章分类
前端