js实现视频切片
使用MediaSource API实现视频切片
MediaSource API允许动态构建媒体源,适合实现视频切片播放。核心步骤包括创建MediaSource对象、监听sourceopen事件、添加SourceBuffer。
const video = document.getElementById('video');
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', () => {
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
// 获取并追加视频切片
fetchVideoSegment(0, sourceBuffer);
});
function fetchVideoSegment(segmentIndex, sourceBuffer) {
fetch(`/video/segment-${segmentIndex}.mp4`)
.then(response => response.arrayBuffer())
.then(data => {
sourceBuffer.appendBuffer(data);
sourceBuffer.addEventListener('updateend', () => {
if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
fetchVideoSegment(segmentIndex + 1, sourceBuffer);
}
});
});
}
使用Range请求实现部分加载
通过HTTP Range头部可以实现视频文件的按需加载,无需预先切片。这种方法适合大文件的分块传输。

const video = document.querySelector('video');
video.addEventListener('progress', () => {
const buffered = video.buffered;
if (buffered.length > 0) {
const end = buffered.end(buffered.length - 1);
if (end > video.currentTime + 5) return;
const rangeStart = Math.floor(end);
const rangeEnd = rangeStart + 1024 * 1024 * 2; // 2MB chunks
fetch(video.src, {
headers: { 'Range': `bytes=${rangeStart}-${rangeEnd}` }
}).then(response => {
// 处理接收到的视频数据块
});
}
});
使用FFmpeg进行视频预切片
服务端可以使用FFmpeg将视频预切成多个小文件,便于前端按需加载。以下是通过命令行进行切片的示例:
ffmpeg -i input.mp4 -c copy -map 0 -segment_time 10 -f segment output%03d.mp4
这个命令会将视频按每10秒切分为多个片段,生成output000.mp4、output001.mp4等文件。

MSE扩展方案
对于更复杂的场景,可以结合MSE(Media Source Extensions)和时间轴控制实现精细切片管理:
class VideoSegmentLoader {
constructor(videoElement) {
this.mediaSource = new MediaSource();
videoElement.src = URL.createObjectURL(this.mediaSource);
this.sourceBuffer = null;
this.queue = [];
this.loading = false;
}
init() {
return new Promise((resolve) => {
this.mediaSource.addEventListener('sourceopen', () => {
this.sourceBuffer = this.mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
resolve();
});
});
}
appendSegment(segment) {
if (this.sourceBuffer.updating || this.loading) {
this.queue.push(segment);
} else {
this._loadSegment(segment);
}
}
_loadSegment(segment) {
this.loading = true;
fetch(segment.url)
.then(response => response.arrayBuffer())
.then(data => {
this.sourceBuffer.appendBuffer(data);
this.sourceBuffer.addEventListener('updateend', () => {
this.loading = false;
if (this.queue.length > 0) {
this._loadSegment(this.queue.shift());
}
});
});
}
}
性能优化建议
实现视频切片时需要考虑缓冲策略和网络状况。设置合理的预加载阈值,避免频繁请求小切片。使用ABR(自适应比特率)技术可以根据网络条件动态切换不同质量的视频切片。
监控缓冲区和播放位置的关系,提前加载后续切片。考虑使用Web Worker处理视频数据的解码和缓冲管理,减轻主线程负担。对于直播场景,需要使用不同的切片策略和协议如HLS或DASH。






