最近在对超大音频的渐进式请求实现上面消耗了不少时间,主要是因为一对音频的基本原理不太理解,二刚开始的时候太依赖插件,三网上这块的资料找不到只能靠自己摸索。由于交互复杂加上坑比较多,我怕描述不清,这里主要根据问题来做描述(前提你需要对wavesurfer.js有一定的了解)我的这篇博客有做说明:
未加载部分:
后端接口描述:
a、音频主要信息接口:获取总时长、字节数、总字节、音频格式等。
b、 分段请求接口:根据字节参数,传来对应段的音频。
1、如何设置容器的长度,及滚动条的设置?
html布局
<div class="wave-wrapper" ref="waveWrapper" > <div class="wave-container" :style="{width: waveContainerWidth=='100%'?'100%':waveContainerWidth+'px'}" @click="containerClick($event)" > <div id="waveform" ref="waveform" class="wave-form" :style="{width: waveFormWidth=='100%'?'100%':waveFormWidth+'px',left: waveFormLeft+'px'}" @click.stop ></div> </div> </div>waveform是wavesurfer渲染实际分段音频的容器,waveWrapper是音频的容器,这里追溯wavesurfer的源码,可以知道它对音频的解析是 **像素值=秒数*20**;因此从后端获取总时长后,设置waveContainerWidth即可。样式设置为overflow-y:auto。
// 音频宽:防止音频过短,渲染不完 let dWidth = Math.round(that.duration * 20); that.waveContainerWidth = that.wrapperWidth > dWidth ? that.wrapperWidth : dWidth; 2、音频分几段请求?
// 后台传入的音频信息存储 that.audioInfo = res; // 音频时长 that.duration = parseInt(res.duration / 1000000); // 如果音频的长度大于500s分段请求,每段100s // 1分钟的字节数[平均] = 比特率(bps) * 时长(s) / 8 that.rangeBit = that.duration > 500 ? (that.audioInfo.bitrate * that.rangeSecond) / 8 : that.audioInfo.size; // 总段数 that.segNumbers = Math.ceil(that.audioInfo.size / that.rangeBit);3、如何请求音频文件,如何实现预加载?
wavesurfer.js渲染音频的方式之一是根据WebAudio来渲染的。由于后端传给我的文件是arraybuffer的格式,那么这里就需要使用WebAudio读取和解析buffer文件的功能,这些wavesurfer.js内部已实现。只需要将文件传给它就可以了。这里我采用了预加载功能,即每加载一段音频就绘制当段的音频,但同时请求并缓存下一段音频。
/** * 获取音频片段 * @param segNumber 加载第几段 * @param justCache 仅仅缓存 true 仅缓存不加载 * @param initLoad 初始加载 */ getAudioSeg(segNumber, justCache, initLoad) { let that = this; let xhr = new XMLHttpRequest(); let reqUrl = location.origin; xhr.open( "GET", `${reqUrl}/storage/api/audio/${this.audioInfo.code}`, true ); xhr.responseType = "arraybuffer"; let startBit = this.rangeBit * (segNumber - 1); let endBit = this.rangeBit * segNumber; xhr.setRequestHeader("Range", `bytes=${startBit}-${endBit}`); xhr.onload = function()
