Tôi không biết chắc chắn vấn đề thực sự bạn đang gặp phải là gì.
Có thể Chrome có giới hạn kích thước tối đa cho những gì họ lưu trong bộ nhớ cache và nếu đúng như vậy, thì việc không sử dụng Phạm vi yêu cầu sẽ không giải quyết được gì.
Một lời giải thích khả dĩ khác là bộ nhớ đệm không thực sự là một nhiệm vụ đơn giản.
Không nhìn thấy tệp của bạn, thật khó để biết chắc chắn trong trường hợp nào, nhưng bạn phải hiểu rằng để phát phương tiện, trình duyệt không cần phải tìm nạp toàn bộ tệp.
Chẳng hạn, bạn rất có thể phát tệp video trong phần tử <audio>, vì luồng video sẽ không được sử dụng, trình duyệt rất có thể bỏ qua hoàn toàn và chỉ tải xuống luồng âm thanh. Không chắc chắn nếu có, nhưng họ có thể. Hầu hết các định dạng phương tiện thực hiện các luồng âm thanh và video riêng biệt trong tệp và vị trí byte của chúng được đánh dấu trong siêu dữ liệu.
Họ chắc chắn có thể lưu trữ các Yêu cầu Phạm vi mà họ thực hiện, nhưng tôi nghĩ họ vẫn còn khá hiếm.
Nhưng vì có thể vô hiệu hóa các Yêu cầu Phạm vi, bạn phải biết rằng một số trình duyệt (Safari) sẽ không phát phương tiện của bạn nếu máy chủ của bạn không cho phép Yêu cầu Phạm vi.
Vì vậy, ngay cả sau đó, nó có thể không phải là những gì bạn muốn.
Điều đầu tiên bạn có thể muốn thử là tối ưu hóa video của bạn để sử dụng web. Thay vì mp4, phục vụ một tệp webm. Chúng thường sẽ chiếm ít không gian hơn cho cùng một chất lượng và có thể bạn sẽ tránh được giới hạn kích thước tối đa .
Nếu tệp kết quả vẫn quá lớn, thì một giải pháp bẩn sẽ là sử dụng MediaSource để tệp được giữ trong bộ nhớ và bạn chỉ cần tìm nạp nó một lần.
Trong ví dụ sau, tệp sẽ chỉ được tìm nạp hoàn toàn một lần, bởi các đoạn 1MB, được MediaSource truyền phát khi nó được tìm nạp và sau đó chỉ dữ liệu trong bộ nhớ sẽ được sử dụng cho các lần phát lặp:
document.getElementById('streamVid').onclick = e => (async () => {
const url = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm';
// you must know the mimeType of your video before hand.
const type = 'video/webm; codecs="vp8, vorbis"';
if( !MediaSource.isTypeSupported( type ) ) {
throw 'Unsupported';
}
const source = new MediaSource();
source.addEventListener('sourceopen', sourceOpen);
document.getElementById('out').src = URL.createObjectURL( source );
// async generator Range-Fetcher
async function* fetchRanges( url, chunk_size = 1024 * 1024 ) {
let chunk = new ArrayBuffer(1);
let cursor = 0;
while( chunk.byteLength ) {
const resp = await fetch( url, {
method: "get",
headers: { "Range": "bytes=" + cursor + "-" + ( cursor += chunk_size ) }
}
)
chunk = resp.ok && await resp.arrayBuffer();
cursor++; // add one byte for next iteration, Ranges are inclusive
yield chunk;
}
}
// set up our MediaSource
async function sourceOpen() {
const buffer = source.addSourceBuffer( type );
buffer.mode = "sequence";
// waiting forward to appendAsync...
const appendBuffer = ( chunk ) => {
return new Promise( resolve => {
buffer.addEventListener( 'update', resolve, { once: true } );
buffer.appendBuffer( chunk );
} );
}
// while our RangeFetcher is running
for await ( const chunk of fetchRanges(url) ) {
if( chunk ) { // append to our MediaSource
await appendBuffer( chunk );
}
else { // when done
source.endOfStream();
}
}
}
})().catch( console.error );
<button id="streamVid">stream video</button>
<video id="out" controls muted autoplay loop></video>