前言:直接加载视频资源会有视频资源泄露的风险,用视频流分片加载可以快速加载视频,并且避免视频资源泄露。视频资源是MP4格式。
1.对视频资源有要求
使用MediaSource加载视频资源,实现分片加载对视频编码格式有要求,
可以参考。
MP4文件主要由ftyp,mdat,moov三部分组成。
三部分的主要职责:
(1)ftyp 记录了mp4格式,编码格式之类的一些基本信息
(2)mdat记录了视频媒体信息(mdat的体积往往非常的大,几乎等于MP4总大小)
(3)moov是如同检索表一样的存在,里面记录了每一帧对应的数据在哪里等等
而这三部分的在mp4视频中的顺序决定了该视频支不支持边下边播,具体主要是mdat和moov两个部分的顺序,需要moov在mdat前,也就是先加载类似视频的索引才能实现该效果。
可以下载两个文件
1.查看MP4编码格式 mp4info
2.转换编码格式 faststart
2.分片加载视频流
转换完格式的视频资源,默认加载就自动分片了,可以直接在player.src中插入请求地址,我这个是get请求直接返回流。这种要求后端代码做分片限制。
player.src = 'http://xxx'
但是分的片不是固定的。
想要固定分片可以通过限制请求头的Range,并迭代请求。
//获取视频
function getVideo(video_size) {
//video_size 单位MB video_size*1024*1024 单位B 字节
const totalSize = video_size * 1024 * 1024
const chunkSize = Math.ceil(totalSize / 5)//浏览器同域名请求的最大限制,谷歌浏览器最多六路
const numChunks = 5
let index = 0
var startByte,endByte
//获取视频流对视频格式有要求
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ("MediaSource" in window && MediaSource.isTypeSupported(mimeCodec)) {
const mediaSource = new MediaSource();
player.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", sourceOpen);
} else {
console.error("Unsupported MIME type or codec: ", mimeCodec);
}
function sourceOpen(_) {
const mediaSource = this;
const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
function send(){
if (index >= numChunks) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream()
})
}else{
startByte = index * chunkSize
endByte = Math.min(startByte + chunkSize - 1, totalSize - 1)
var xhr = new XMLHttpRequest();
xhr.open("get", 'http://XXX')
xhr.responseType = "arraybuffer";//可以分配一段可以存放数据的连续内存区域。
xhr.setRequestHeader('Range', `bytes=${startByte}-${endByte}`);//限制range
xhr.onload = function () {
index++
sourceBuffer.appendBuffer(xhr.response);//资源拼接
send()
player.play();
};
xhr.send();
}
}
send()
}
这样的前端分片对请求次数有限制,谷歌浏览器中第7次请求报错。解决办法参考。