更新:
我的第一次尝试是在下载这些块时收集它们,然后再将它们放回去,内存占用很大(视频大小的2-3倍)。使用一个ReadableStream有更低的内存占用(对于1.1GB的mkv文件,内存使用量大约为150MB)。代码主要从这里的片段进行了适应,并仅有我进行了少量修改:
https://github.com/AnthumChris/fetch-progress-indicators/blob/master/fetch-basic/supported-browser.js
<div id="progress_bar"></div>
<video id="video_player"></video>
const elProgress = document.getElementById('progress_bar'),
player = document.getElementById('video_player');
function getVideo2() {
let contentType = 'video/mp4';
fetch('$pathToVideo.mp4')
.then(response => {
const contentEncoding = response.headers.get('content-encoding');
const contentLength = response.headers.get(contentEncoding ? 'x-file-size' : 'content-length');
contentType = response.headers.get('content-type') || contentType;
if (contentLength === null) {
throw Error('Response size header unavailable');
}
const total = parseInt(contentLength, 10);
let loaded = 0;
return new Response(
new ReadableStream({
start(controller) {
const reader = response.body.getReader();
read();
function read() {
reader.read().then(({done, value}) => {
if (done) {
controller.close();
return;
}
loaded += value.byteLength;
progress({loaded, total})
controller.enqueue(value);
read();
}).catch(error => {
console.error(error);
controller.error(error)
})
}
}
})
);
})
.then(response => response.blob())
.then(blob => {
let vid = URL.createObjectURL(blob);
player.style.display = 'block';
player.type = contentType;
player.src = vid;
elProgress.innerHTML += "<br /> Press play!";
})
.catch(error => {
console.error(error);
})
}
function progress({loaded, total}) {
elProgress.innerHTML = Math.round(loaded / total * 100) + '%';
}
第一次尝试(较差,适用于较小的文件)
我的原始方法。对于一个1.1GB的mkv文件,在文件下载时,内存使用率会慢慢上升到1.3GB,当块被合并时,则会急剧飙升至约3.5Gb。一旦视频开始播放,选项卡的内存使用量会回落到约200MB,但Chrome的整体使用量仍保持在1GB以上。
你可以通过累加视频的每个块(value
)来构建blob自己,而不是调用response.blob()
来获取blob。这个示例是从这里改编的:https://javascript.info/fetch-progress#0d0g7tutne
receivedLength += value.length;
chunks.push(value);
let Uint8Chunks = new Uint8Array(receivedLength), position = 0;
for (let chunk of chunks) {
Uint8Chunks.set(chunk, position);
position += chunk.length;
}
const blob = new Blob([Uint8Chunks], {type: 'video/mp4'})
const blob = await response.blob();
。 - chiliNUT