wavesurfer.js 波形图超长视频处理

68 阅读2分钟

简介

最近在开发一个基于 ffmpeg 来进行视频分段的功能,使用了wavesurfer来显示波形图,遇到了一些坑,来和大家分享一下。

安装

npm install --save wavesurfer.js

使用

基础使用

import WaveSurfer from 'wavesurfer.js'

const wavesurfer = WaveSurfer.create({
  container: document.body,
  waveColor: 'rgb(200, 0, 200)',
  progressColor: 'rgb(100, 0, 100)',
  url: '/examples/audio/demo.wav',
})

wavesurfer.on('click', () => {
  wavesurfer.play()
})

与视频联动使用

/*
<html>
  <video
    src="/examples/audio/modular.mp4"
    controls
    playsinline
    style="width: 100%; max-width: 600px; margin: 0 auto; display: block;"
  />
</html>
*/

import WaveSurfer from 'wavesurfer.js'

// Initialize wavesurfer.js
const ws = WaveSurfer.create({
  container: document.body,
  waveColor: 'rgb(200, 0, 200)',
  progressColor: 'rgb(100, 0, 100)',
  // Pass the video element in the `media` param
  media: document.querySelector('video'),
})

Pasted image 20251124100858.png

高级使用

以上的这些都不是重点,都是铺垫,主要内容是下面的内容。

如果你真的按照上面的去实践了,简单试了五分钟的视频,发现速度非常快,效果也非常好,直到测试扔了一个小时的视频进去,加载速度可能到了分钟级,内存占用到了 G 级别,甚至再大一点,你的浏览器直接崩溃,但在现实场景中,这种长度的视频其实并不少见。 又或者测试加载了 flv 视频,虽然你使用了 flv.js 进行了正常的播放,但是你的波形图却没法显示。

接下来聊一下如何处理这些问题,这个问题纯前端是无法解决的,需要后端来进行支持,原理也非常简单,使用 ffmpeg 提取出 wav 音频流,再使用 audiowaveform 转换为 peaks 数据,再将 peaks 数据回传给 wavesurfer 即可展示。

ffmpeg 提取

命令也非常简单,-ac 1 用于只处理单个通道:

ffmpeg -i input.mp4 -vn -acodec pcm_s16le -ac 1 audio.wav

audiowaveform 解析

首先你得去项目中下载安装依赖,接下来执行:

audiowaveform -i audio.wav -o peaks.json

也可以使用 --pixels-per-second 20 来减小生成的文件大小,相应的精细度也会变低

wavesurfer 生成

接下来再回到前端项目之中

const ws = WaveSurfer.create({
  container: "#waveform",
  waveColor: "#4F4A85",
  progressColor: "#383351",
  peaks: [peaks],  // 这里的peaks取生成json中的data数据,
  duration: duration  // duration是视频或音频的时长,单位秒
});

// 如果需要与视频进行联动,你得手动实现,伪代码,按照你的框架自行修改
// 首先监听video的timeupdate事件
video.on("timeupdate", ()=>ws.setTime(video.currentTime););
// 监听ws的interaction事件
ws.on("interaction", ()=>video.currentTime = time;)