简介
最近在开发一个基于 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'),
})
高级使用
以上的这些都不是重点,都是铺垫,主要内容是下面的内容。
如果你真的按照上面的去实践了,简单试了五分钟的视频,发现速度非常快,效果也非常好,直到测试扔了一个小时的视频进去,加载速度可能到了分钟级,内存占用到了 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;)