Media Source Extensions API (MSE).
Пример (
описание): создается blob-ссылка, файл подгружается частями в зависимости от времени проигрывания и добавляется в ее медиабуфер. Изменил пример, убрал зависимость от времени проигрывания:
var video = document.querySelector('video');
var assetURL = 'frag_bunny.mp4';
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
var totalLength = 0;
var loadedLength = 0;
var segmentLength = 1024 * 1024;
var mediaSource = null;
var sourceBuffer = null;
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
mediaSource = new MediaSource;
mediaSource.addEventListener('sourceopen', onSourceOpen);
video.src = URL.createObjectURL(mediaSource);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function onSourceOpen() {
sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
sourceBuffer.addEventListener('updateend', onUpdateEnd);
loadFileLength(assetURL, onLoadFileLength);
};
function onUpdateEnd() {
if (loadedLength < totalLength) {
loadFileRange(assetURL, loadedLength, Math.min(loadedLength + segmentLength, totalLength), onLoadFileRange);
} else {
mediaSource.endOfStream();
}
}
function loadFileLength(url, cb) {
var xhr = new XMLHttpRequest;
xhr.open('HEAD', url);
xhr.onload = function () {
cb(+xhr.getResponseHeader('Content-Length'));
};
xhr.send();
};
function onLoadFileLength(fileLength) {
totalLength = fileLength;
onUpdateEnd();
video.addEventListener('canplay', function () {
//video.play();
});
}
function loadFileRange(url, start, end, cb) {
var xhr = new XMLHttpRequest;
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.requestHeaderRange = 'bytes=' + start + '-' + end;
xhr.setRequestHeader('Range', xhr.requestHeaderRange);
xhr.onload = function () {
//logHeaders(xhr);
loadedLength += end - start + 1;
cb(xhr.response);
};
xhr.send();
};
function onLoadFileRange(chunk) {
sourceBuffer.appendBuffer(chunk);
}
function logHeaders(xhr) {
console.log('Range:', xhr.requestHeaderRange,
'Content-Length:', xhr.getResponseHeader('Content-Length'),
'Content-Range:', xhr.getResponseHeader('Content-Range'));
}