大的音视屏文件播放思路
在前端播放一个大小为 10GB 的视频时,直接下载整个视频文件然后播放显然是不切实际的,因为这样会导致极大的延迟和带宽消耗。为了尽快开始播放大文件,可以采用以下几种技术来优化视频播放体验。
1.视频流式传输 (Streaming)
流式传输允许前端在不下载完整文件的情况下,就能开始播放视频。具体的方法有两种常见的流式传输方式:
HLS (HTTP Live Streaming)
HLS 是 Apple 提供的一种基于 HTTP 的流媒体协议,可以将大视频文件分割成多个小的 .ts 片段(通常几秒钟一个),并通过 .m3u8 播放列表进行管理。前端播放器根据网络情况动态加载这些小片段,而不需要等待整个视频文件加载完成。
- 优势:支持实时加载并开始播放,适应不同的网络带宽,避免了一开始就下载整个大文件。
- 实现方式:使用如 Video.js、hls.js 等 JavaScript 库播放 HLS 流媒体。
<video id="video"></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
if (Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('https://example.com/playlist.m3u8'); // 加载 .m3u8 播放列表
hls.attachMedia(video); // 将媒体附加到 <video> 元素
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play(); // 播放视频
});
}
</script>
DASH (Dynamic Adaptive Streaming over HTTP)
DASH 是一种类似 HLS 的流媒体协议,适用于动态调整视频质量以适应带宽条件。视频文件被切分为多个片段,并且客户端会根据带宽情况自动选择合适的清晰度播放。
- 优势:支持多种设备和浏览器,提供了与 HLS 类似的流式传输体验。
- 实现方式:可以使用 Shaka Player 或 dash.js 来播放 DASH 流媒体
<video id="video" controls> <source src="https://example.com/video.mpd" type="application/dash+xml"> </video>
2. 使用 Media Source Extensions (MSE)
是一个允许网页动态地创建媒体流并将其送入 <video> 元素进行播放的浏览器 API。MSE 使得浏览器能够支持自适应流媒体(如 HLS、DASH)和实时视频播放(例如,视频片段的动态加载和拼接)。前端通过使用 MSE 可以更灵活地处理视频源,按需加载并控制视频流的播放。
<video id="video" controls></video>
<script>
// 创建 MediaSource 对象
const mediaSource = new MediaSource();
const video = document.getElementById('video');
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', onSourceOpen);
function onSourceOpen() {
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001F"');
fetchVideoSegment('path/to/video/segment1.mp4', sourceBuffer);
}
function fetchVideoSegment(url, sourceBuffer) {
fetch(url)
.then(response => response.arrayBuffer())
.then(data => {
// 将视频数据添加到 SourceBuffer
sourceBuffer.appendBuffer(data);
// 等待更新结束后加载下一个片段
sourceBuffer.addEventListener('updateend', () => {
console.log('Segment loaded, loading next...');
// 加载下一个视频片段
fetchNextSegment();
});
});
}
function fetchNextSegment() {
fetchVideoSegment('path/to/video/segment2.mp4', sourceBuffer);
}
</script>
3.使用 JavaScript 实现 Range 请求(分片下载)
在渐进式下载中,你可以通过 JavaScript 控制 <video> 元素和 HTTP Range 请求。首先,我们可以使用 fetch() API 和 Range 请求头来加载视频的一部分。接下来,将其传输到 <video> 元素中进行播放。
服务器端需要支持 HTTP Range 请求。大部分现代 HTTP 服务器(如 Apache、Nginx)默认支持 Range 请求,但有些老旧的服务器可能需要额外配置。
服务器示例:
-
Nginx 配置: 在 Nginx 配置文件中,可以启用
range模式来支持渐进式下载:这确保了服务器在接收到
Range请求时,返回文件的特定部分,而不是整个文件。
客户端代码示例:
const video = document.querySelector('video');
const videoUrl = 'video.mp4';
// 使用 fetch 发起 Range 请求
fetch(videoUrl, {
headers: {
'Range': 'bytes=0-999999' // 请求文件的前 1MB
}
})
.then(response => response.blob())
.then(blob => {
// 使用 Blob 对象将视频数据加载到 video 元素
video.src = URL.createObjectURL(blob);
video.play();
});
// 假设进度条向前推进,继续加载剩余数据
function loadNextChunk(startByte, endByte) {
fetch(videoUrl, {
headers: {
'Range': `bytes=${startByte}-${endByte}` // 请求接下来的数据部分
}
})
.then(response => response.blob())
.then(blob => {
// 将数据追加到视频元素
const videoSourceBuffer = new MediaSource();
const sourceBuffer = videoSourceBuffer.addSourceBuffer('video/mp4; codecs="avc1.4d401f, mp4a.40.2"');
sourceBuffer.appendBuffer(blob);
});
}
4、总结
- MSE:提供了高度的灵活性和控制,适用于需要按需加载、动态拼接视频片段、低延迟播放等复杂场景。它适合实时流媒体、直播和大文件按需加载的场景。
- Range 请求:实现简单,适用于视频文件的按需加载,但不支持自适应比特率或流媒体协议,因此它更适合于简单的视频播放需求,且不适用于需要自适应质量或高效流控制的场景。
- HLS:适用于直播、点播等流媒体应用,特别是在网络条件变化时,HLS 的自适应比特率特性能够提供更好的用户体验。它要求服务器端对视频进行切割并提供
.m3u8播放列表,适合大规模的视频流传输。
根据应用场景选择合适的技术:
- 复杂流媒体应用(低延迟、动态质量调整等):推荐使用 MSE。
- 简单的按需视频加载:可以使用 Range 请求。
- 大规模流媒体直播或点播(需要自适应比特率):推荐使用 HLS。

浙公网安备 33010602011771号