如何在 Nuxt 3 中使用 wavesurfer.js

  • 如何在 Nuxt 3 中使用 wavesurfer.js已关闭评论
  • 138 次浏览
  • A+
所属分类:Web前端
摘要

在项目中安装 wavesurfer.js如果你的根目录中没有 components 目录则需要创建该目录,并在此目录中创建 WaveSurfer.vue 内容如下:


安装 wavesurfer.js

在项目中安装 wavesurfer.js

npm install --save wavesurfer.js 

常规方式引入

如果你的根目录中没有 components 目录则需要创建该目录,并在此目录中创建 WaveSurfer.vue 内容如下:

<template>     <div ref="wavesurferMain"></div>   </template>   <script setup>   import WaveSurfer from 'wavesurfer.js'      const props = defineProps({     src:{       type:String,       required:true     },     options:{       type:Object,     }   }); const wavesurferMain = ref(null);   const waveSurfer = ref(null);         let options = props.options;   let wsOptions = Object.assign({         container: wavesurferMain.value       },       options);    waveSurfer.value = new WaveSurfer.create(wsOptions);   waveSurfer.value.load(props.src);  </script> 

然后我们集成该组件,在这个例子中我们将在 app.vue 直接引用,并且我将测试音频文件 demo.wav,放在根目录的public 中。

<template>     <div>     <WaveSurfer src="/demo.wav":options="waveSurferOption" />   </div> </template>   <script setup>   const waveSurferOption = {     height: 340,     progressColor: '#e03639',     waveColor: '#e7e7e7',     cursorColor: '#FFDDDD',     barWidth: 2,     mediaControls: true,     backend: 'MediaElement',     scrollParent:true,     xhr: {       mode: 'no-cors'     }   };   </script> 

现在执行 npm run dev ,页面将报错 self is not defined
这是因为在 setup 这个生命周期中,DOM 节点并未创建,所以我们需要在mounted 阶段进行导入。

正确的引入方式

更改 WaveSurfer.vue 文件内容如下:

<template>     <div ref="wavesurferMain"></div>   </template>   <script setup>   const props = defineProps({     src:{       type:String,       required:true     },     options:{       type:Object,     }   });      const wavesurferMain = ref(null);   const waveSurfer = ref(null);      onMounted(async ()=>{     const WaveSurfer = (await import('wavesurfer.js')).default;     const options = props.options;     const wsOptions = Object.assign({           container: wavesurferMain.value         },         options);     waveSurfer.value = new WaveSurfer.create(wsOptions);     waveSurfer.value.load(props.src);   });   </script> 

现在你应该能看到已经可以正常加载了。

加载插件

加载方式和插件一样,官方的插件在 wavesurfer.js/dist/plugin 目录下,这个例子将加载时间线插件如下:

<template>     <div ref="wavesurferMain"></div>     <div ref="waveTimeline"></div>   </template>   <script setup>   const props = defineProps({     src:{       type:String,       required:true     },     options:{       type:Object,     }   });      const wavesurferMain = ref(null);   const waveTimeline = ref(null);   const waveSurfer = ref(null);      onMounted(async ()=>{     const WaveSurfer = (await import('wavesurfer.js')).default;     const Timeline  = (await import('wavesurfer.js/dist/plugin/wavesurfer.timeline')).default;     const options = props.options;     const wsOptions = Object.assign({           container: wavesurferMain.value,           plugins:[             Timeline.create({container:waveTimeline.value})           ]         },         options);     waveSurfer.value = new WaveSurfer.create(wsOptions);     waveSurfer.value.load(props.src);      });   </script> 

加载波形数据

如果音频文件过大,使用插件原生的波形生成方式会非常慢。这个时候可以通过服务端生成波形数据,并让插件直接通过波形数据进行渲染。具体生成方式可以参考官方的解决方案FAQ。在这个项目中,生成波形数据文件后,我把它移动到项目的public中,更改 WaveSurfer.vue 内容如下:

<template>     <div ref="wavesurferMain"></div>     <div ref="waveTimeline"></div>   </template>   <script setup>   const props = defineProps({     src:{       type:String,       required:true     },     peaksData:{       type:String,     },     options:{       type:Object,     }   });      const wavesurferMain = ref(null);   const waveTimeline = ref(null);   const waveSurfer = ref(null);      onMounted(async ()=>{     const WaveSurfer = (await import('wavesurfer.js')).default;     const Timeline  = (await import('wavesurfer.js/dist/plugin/wavesurfer.timeline')).default;     const options = props.options;     const wsOptions = Object.assign({           container: wavesurferMain.value,           plugins:[             Timeline.create({container:waveTimeline.value})           ]         },         options);     waveSurfer.value = new WaveSurfer.create(wsOptions);     fetch(props.peaksData)         .then(response => {           if (!response.ok) {             throw new Error("HTTP error " + response.status);           }           return response.json();         })         .then(peaks => {           waveSurfer.value.load(props.src,peaks.data);         })         .catch((e) => {           console.error('error', e);         });      });   </script> 

app.vue 中变更如下:

<template>     <div>      <WaveSurfer src="/demo.wav" peaks-data="/demo.json" :options="waveSurferOption" />     </div>   </template>   <script setup>   const waveSurferOption = {     height: 340,     progressColor: '#e03639',     waveColor: '#e7e7e7',     cursorColor: '#FFDDDD',     barWidth: 2,     mediaControls: false,     backend: 'MediaElement',     scrollParent:true,     xhr: {       mode: 'no-cors'     }   }   </script> 

暴露插件的方法

现在我们只是正常初始化插件并让它加载了音频文件,目前我们并不能操作它。
因为 Vue3 中,默认并不会暴露 <script setup> 中声明的绑定。我们需要使用 defineExpose 来暴露对应的属性。WaveSurfer.vue 如下变更:

<template>     <div ref="wavesurferMain"></div>     <div ref="waveTimeline"></div>   </template>   <script setup>   const props = defineProps({     src:{       type:String,       required:true     },     peaksData:{       type:String,     },     options:{       type:Object,     }   });      const wavesurferMain = ref(null);   const waveTimeline = ref(null);   const waveSurfer = ref(null);      onMounted(async ()=>{     // 省略逻辑    });   defineExpose(       {         waveSurfer       }   )   </script> 

app.vue 中我们可以这样调用:

<template>     <div>       <WaveSurfer ref="refWaveSurfer" src="/demo.wav" peaks-data="/demo.json" :options="waveSurferOption"/>       <button @click="play">play</button>       <button @click="pause">pause</button>     </div>   </template>   <script setup>   const waveSurferOption = {     height: 340,     progressColor: '#e03639',     waveColor: '#e7e7e7',     cursorColor: '#FFDDDD',     barWidth: 2,     mediaControls: false,     backend: 'MediaElement',     scrollParent:true,     xhr: {       mode: 'no-cors'     }   }   const refWaveSurfer = ref(null);      function play() {     refWaveSurfer.value.waveSurfer.play();  // 调用播放方法  }      function pause(){     refWaveSurfer.value.waveSurfer.pause();  // 调用暂停方法 }   </script> 

项目

你可以在以下仓库看到完整的示例

https://github.com/AnyStudy/nuxt-3-wavesurfer-demo